/home/arjun/llvm-project/mlir/include/mlir/Interfaces/SideEffectInterfaces.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SideEffectInterfaces.h - SideEffect in MLIR --------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file contains traits, interfaces, and utilities for defining and |
10 | | // querying the side effects of an operation. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef MLIR_INTERFACES_SIDEEFFECTS_H |
15 | | #define MLIR_INTERFACES_SIDEEFFECTS_H |
16 | | |
17 | | #include "mlir/IR/OpDefinition.h" |
18 | | |
19 | | namespace mlir { |
20 | | namespace SideEffects { |
21 | | //===----------------------------------------------------------------------===// |
22 | | // Effects |
23 | | //===----------------------------------------------------------------------===// |
24 | | |
25 | | /// This class represents a base class for a specific effect type. |
26 | | class Effect { |
27 | | public: |
28 | | /// This base class is used for derived effects that are non-parametric. |
29 | | template <typename DerivedEffect, typename BaseEffect = Effect> |
30 | | class Base : public BaseEffect { |
31 | | public: |
32 | | using BaseT = Base<DerivedEffect>; |
33 | | |
34 | | /// Return the unique identifier for the base effects class. |
35 | 0 | static TypeID getEffectID() { return TypeID::get<DerivedEffect>(); } Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadES1_E11getEffectIDEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteES1_E11getEffectIDEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateES1_E11getEffectIDEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeES1_E11getEffectIDEv |
36 | | |
37 | | /// 'classof' used to support llvm style cast functionality. |
38 | 0 | static bool classof(const ::mlir::SideEffects::Effect *effect) { |
39 | 0 | return effect->getEffectID() == BaseT::getEffectID(); |
40 | 0 | } Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEE7classofEPKS1_ Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEE7classofEPKS1_ Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEE7classofEPKS1_ Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEE7classofEPKS1_ |
41 | | |
42 | | /// Returns a unique instance for the derived effect class. |
43 | 0 | static DerivedEffect *get() { |
44 | 0 | return BaseEffect::template get<DerivedEffect>(); |
45 | 0 | } Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEE3getEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEE3getEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEE3getEv Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEE3getEv |
46 | | using BaseEffect::get; |
47 | | |
48 | | protected: |
49 | 0 | Base() : BaseEffect(BaseT::getEffectID()) {} Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4ReadENS3_6EffectEEC2Ev Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects5WriteENS3_6EffectEEC2Ev Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects8AllocateENS3_6EffectEEC2Ev Unexecuted instantiation: _ZN4mlir11SideEffects6Effect4BaseINS_13MemoryEffects4FreeENS3_6EffectEEC2Ev |
50 | | }; |
51 | | |
52 | | /// Return the unique identifier for the base effects class. |
53 | 0 | TypeID getEffectID() const { return id; } |
54 | | |
55 | | /// Returns a unique instance for the given effect class. |
56 | 0 | template <typename DerivedEffect> static DerivedEffect *get() { |
57 | 0 | static_assert(std::is_base_of<Effect, DerivedEffect>::value, |
58 | 0 | "expected DerivedEffect to inherit from Effect"); |
59 | 0 |
|
60 | 0 | static DerivedEffect instance; |
61 | 0 | return &instance; |
62 | 0 | } Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects4ReadEEEPT_v Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects5WriteEEEPT_v Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects8AllocateEEEPT_v Unexecuted instantiation: _ZN4mlir11SideEffects6Effect3getINS_13MemoryEffects4FreeEEEPT_v |
63 | | |
64 | | protected: |
65 | 0 | Effect(TypeID id) : id(id) {} |
66 | | |
67 | | private: |
68 | | /// The id of the derived effect class. |
69 | | TypeID id; |
70 | | }; |
71 | | |
72 | | //===----------------------------------------------------------------------===// |
73 | | // Resources |
74 | | //===----------------------------------------------------------------------===// |
75 | | |
76 | | /// This class represents a specific resource that an effect applies to. This |
77 | | /// class represents an abstract interface for a given resource. |
78 | | class Resource { |
79 | | public: |
80 | 0 | virtual ~Resource() {} |
81 | | |
82 | | /// This base class is used for derived effects that are non-parametric. |
83 | | template <typename DerivedResource, typename BaseResource = Resource> |
84 | | class Base : public BaseResource { |
85 | | public: |
86 | | using BaseT = Base<DerivedResource>; |
87 | | |
88 | | /// Returns a unique instance for the given effect class. |
89 | 0 | static DerivedResource *get() { |
90 | 0 | static DerivedResource instance; |
91 | 0 | return &instance; |
92 | 0 | } Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_E3getEv Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_E3getEv |
93 | | |
94 | | /// Return the unique identifier for the base resource class. |
95 | 0 | static TypeID getResourceID() { return TypeID::get<DerivedResource>(); } Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_E13getResourceIDEv Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_E13getResourceIDEv |
96 | | |
97 | | /// 'classof' used to support llvm style cast functionality. |
98 | | static bool classof(const Resource *resource) { |
99 | | return resource->getResourceID() == BaseT::getResourceID(); |
100 | | } |
101 | | |
102 | | protected: |
103 | 0 | Base() : BaseResource(BaseT::getResourceID()){}; Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_15DefaultResourceES1_EC2Ev Unexecuted instantiation: _ZN4mlir11SideEffects8Resource4BaseINS0_32AutomaticAllocationScopeResourceES1_EC2Ev |
104 | | }; |
105 | | |
106 | | /// Return the unique identifier for the base resource class. |
107 | 0 | TypeID getResourceID() const { return id; } |
108 | | |
109 | | /// Return a string name of the resource. |
110 | | virtual StringRef getName() = 0; |
111 | | |
112 | | protected: |
113 | 0 | Resource(TypeID id) : id(id) {} |
114 | | |
115 | | private: |
116 | | /// The id of the derived resource class. |
117 | | TypeID id; |
118 | | }; |
119 | | |
120 | | /// A conservative default resource kind. |
121 | | struct DefaultResource : public Resource::Base<DefaultResource> { |
122 | 0 | StringRef getName() final { return "<Default>"; } |
123 | | }; |
124 | | |
125 | | /// An automatic allocation-scope resource that is valid in the context of a |
126 | | /// parent AutomaticAllocationScope trait. |
127 | | struct AutomaticAllocationScopeResource |
128 | | : public Resource::Base<AutomaticAllocationScopeResource> { |
129 | 0 | StringRef getName() final { return "AutomaticAllocationScope"; } |
130 | | }; |
131 | | |
132 | | /// This class represents a specific instance of an effect. It contains the |
133 | | /// effect being applied, a resource that corresponds to where the effect is |
134 | | /// applied, and an optional value(either operand, result, or region entry |
135 | | /// argument) that the effect is applied to. |
136 | | template <typename EffectT> class EffectInstance { |
137 | | public: |
138 | | EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get()) |
139 | 0 | : effect(effect), resource(resource) {} |
140 | | EffectInstance(EffectT *effect, Value value, |
141 | | Resource *resource = DefaultResource::get()) |
142 | 0 | : effect(effect), resource(resource), value(value) {} |
143 | | |
144 | | /// Return the effect being applied. |
145 | 0 | EffectT *getEffect() const { return effect; } |
146 | | |
147 | | /// Return the value the effect is applied on, or nullptr if there isn't a |
148 | | /// known value being affected. |
149 | 0 | Value getValue() const { return value; } |
150 | | |
151 | | /// Return the resource that the effect applies to. |
152 | 0 | Resource *getResource() const { return resource; } |
153 | | |
154 | | private: |
155 | | /// The specific effect being applied. |
156 | | EffectT *effect; |
157 | | |
158 | | /// The resource that the given value resides in. |
159 | | Resource *resource; |
160 | | |
161 | | /// The value that the effect applies to. This is optionally null. |
162 | | Value value; |
163 | | }; |
164 | | } // namespace SideEffects |
165 | | |
166 | | //===----------------------------------------------------------------------===// |
167 | | // SideEffect Traits |
168 | | //===----------------------------------------------------------------------===// |
169 | | |
170 | | namespace OpTrait { |
171 | | /// This trait indicates that the side effects of an operation includes the |
172 | | /// effects of operations nested within its regions. If the operation has no |
173 | | /// derived effects interfaces, the operation itself can be assumed to have no |
174 | | /// side effects. |
175 | | template <typename ConcreteType> |
176 | | class HasRecursiveSideEffects |
177 | | : public TraitBase<ConcreteType, HasRecursiveSideEffects> {}; |
178 | | } // namespace OpTrait |
179 | | |
180 | | //===----------------------------------------------------------------------===// |
181 | | // Operation Memory-Effect Modeling |
182 | | //===----------------------------------------------------------------------===// |
183 | | |
184 | | namespace MemoryEffects { |
185 | | /// This class represents the base class used for memory effects. |
186 | | struct Effect : public SideEffects::Effect { |
187 | | using SideEffects::Effect::Effect; |
188 | | |
189 | | /// A base class for memory effects that provides helper utilities. |
190 | | template <typename DerivedEffect> |
191 | | using Base = SideEffects::Effect::Base<DerivedEffect, Effect>; |
192 | | |
193 | | static bool classof(const SideEffects::Effect *effect); |
194 | | }; |
195 | | using EffectInstance = SideEffects::EffectInstance<Effect>; |
196 | | |
197 | | /// The following effect indicates that the operation allocates from some |
198 | | /// resource. An 'allocate' effect implies only allocation of the resource, and |
199 | | /// not any visible mutation or dereference. |
200 | | struct Allocate : public Effect::Base<Allocate> {}; |
201 | | |
202 | | /// The following effect indicates that the operation frees some resource that |
203 | | /// has been allocated. An 'allocate' effect implies only de-allocation of the |
204 | | /// resource, and not any visible allocation, mutation or dereference. |
205 | | struct Free : public Effect::Base<Free> {}; |
206 | | |
207 | | /// The following effect indicates that the operation reads from some resource. |
208 | | /// A 'read' effect implies only dereferencing of the resource, and not any |
209 | | /// visible mutation. |
210 | | struct Read : public Effect::Base<Read> {}; |
211 | | |
212 | | /// The following effect indicates that the operation writes to some resource. A |
213 | | /// 'write' effect implies only mutating a resource, and not any visible |
214 | | /// dereference or read. |
215 | | struct Write : public Effect::Base<Write> {}; |
216 | | } // namespace MemoryEffects |
217 | | |
218 | | //===----------------------------------------------------------------------===// |
219 | | // SideEffect Interfaces |
220 | | //===----------------------------------------------------------------------===// |
221 | | |
222 | | /// Include the definitions of the side effect interfaces. |
223 | | #include "mlir/Interfaces/SideEffectInterfaces.h.inc" |
224 | | |
225 | | //===----------------------------------------------------------------------===// |
226 | | // SideEffect Utilities |
227 | | //===----------------------------------------------------------------------===// |
228 | | |
229 | | /// Return true if the given operation is unused, and has no side effects on |
230 | | /// memory that prevent erasing. |
231 | | bool isOpTriviallyDead(Operation *op); |
232 | | |
233 | | /// Return true if the given operation would be dead if unused, and has no side |
234 | | /// effects on memory that would prevent erasing. This is equivalent to checking |
235 | | /// `isOpTriviallyDead` if `op` was unused. |
236 | | bool wouldOpBeTriviallyDead(Operation *op); |
237 | | |
238 | | } // end namespace mlir |
239 | | |
240 | | #endif // MLIR_INTERFACES_SIDEEFFECTS_H |