MLIR  17.0.0git
SideEffectInterfaces.h
Go to the documentation of this file.
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_SIDEEFFECTINTERFACES_H
15 #define MLIR_INTERFACES_SIDEEFFECTINTERFACES_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:
33 
34  /// Return the unique identifier for the base effects class.
35  static TypeID getEffectID() { return TypeID::get<DerivedEffect>(); }
36 
37  /// 'classof' used to support llvm style cast functionality.
38  static bool classof(const ::mlir::SideEffects::Effect *effect) {
39  return effect->getEffectID() == BaseT::getEffectID();
40  }
41 
42  /// Returns a unique instance for the derived effect class.
43  static DerivedEffect *get() {
44  return BaseEffect::template get<DerivedEffect>();
45  }
46  using BaseEffect::get;
47 
48  protected:
49  Base() : BaseEffect(BaseT::getEffectID()) {}
50  };
51 
52  /// Return the unique identifier for the base effects class.
53  TypeID getEffectID() const { return id; }
54 
55  /// Returns a unique instance for the given effect class.
56  template <typename DerivedEffect>
57  static DerivedEffect *get() {
58  static_assert(std::is_base_of<Effect, DerivedEffect>::value,
59  "expected DerivedEffect to inherit from Effect");
60 
61  static DerivedEffect instance;
62  return &instance;
63  }
64 
65 protected:
66  Effect(TypeID id) : id(id) {}
67 
68 private:
69  /// The id of the derived effect class.
70  TypeID id;
71 };
72 
73 //===----------------------------------------------------------------------===//
74 // Resources
75 //===----------------------------------------------------------------------===//
76 
77 /// This class represents a specific resource that an effect applies to. This
78 /// class represents an abstract interface for a given resource.
79 class Resource {
80 public:
81  virtual ~Resource() = default;
82 
83  /// This base class is used for derived effects that are non-parametric.
84  template <typename DerivedResource, typename BaseResource = Resource>
85  class Base : public BaseResource {
86  public:
88 
89  /// Returns a unique instance for the given effect class.
90  static DerivedResource *get() {
91  static DerivedResource instance;
92  return &instance;
93  }
94 
95  /// Return the unique identifier for the base resource class.
96  static TypeID getResourceID() { return TypeID::get<DerivedResource>(); }
97 
98  /// 'classof' used to support llvm style cast functionality.
99  static bool classof(const Resource *resource) {
100  return resource->getResourceID() == BaseT::getResourceID();
101  }
102 
103  protected:
104  Base() : BaseResource(BaseT::getResourceID()){};
105  };
106 
107  /// Return the unique identifier for the base resource class.
108  TypeID getResourceID() const { return id; }
109 
110  /// Return a string name of the resource.
111  virtual StringRef getName() = 0;
112 
113 protected:
114  Resource(TypeID id) : id(id) {}
115 
116 private:
117  /// The id of the derived resource class.
118  TypeID id;
119 };
120 
121 /// A conservative default resource kind.
122 struct DefaultResource : public Resource::Base<DefaultResource> {
123  StringRef getName() final { return "<Default>"; }
124 };
125 
126 /// An automatic allocation-scope resource that is valid in the context of a
127 /// parent AutomaticAllocationScope trait.
129  : public Resource::Base<AutomaticAllocationScopeResource> {
130  StringRef getName() final { return "AutomaticAllocationScope"; }
131 };
132 
133 /// This class represents a specific instance of an effect. It contains the
134 /// effect being applied, a resource that corresponds to where the effect is
135 /// applied, and an optional symbol reference or value(either operand, result,
136 /// or region entry argument) that the effect is applied to, and an optional
137 /// parameters attribute further specifying the details of the effect.
138 template <typename EffectT>
140 public:
141  EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get())
142  : effect(effect), resource(resource) {}
143  EffectInstance(EffectT *effect, Value value,
144  Resource *resource = DefaultResource::get())
145  : effect(effect), resource(resource), value(value) {}
146  EffectInstance(EffectT *effect, SymbolRefAttr symbol,
147  Resource *resource = DefaultResource::get())
148  : effect(effect), resource(resource), value(symbol) {}
149  EffectInstance(EffectT *effect, Attribute parameters,
150  Resource *resource = DefaultResource::get())
151  : effect(effect), resource(resource), parameters(parameters) {}
152  EffectInstance(EffectT *effect, Value value, Attribute parameters,
153  Resource *resource = DefaultResource::get())
154  : effect(effect), resource(resource), value(value),
155  parameters(parameters) {}
156  EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters,
157  Resource *resource = DefaultResource::get())
158  : effect(effect), resource(resource), value(symbol),
159  parameters(parameters) {}
160 
161  /// Return the effect being applied.
162  EffectT *getEffect() const { return effect; }
163 
164  /// Return the value the effect is applied on, or nullptr if there isn't a
165  /// known value being affected.
166  Value getValue() const { return value ? value.dyn_cast<Value>() : Value(); }
167 
168  /// Return the symbol reference the effect is applied on, or nullptr if there
169  /// isn't a known smbol being affected.
170  SymbolRefAttr getSymbolRef() const {
171  return value ? value.dyn_cast<SymbolRefAttr>() : SymbolRefAttr();
172  }
173 
174  /// Return the resource that the effect applies to.
175  Resource *getResource() const { return resource; }
176 
177  /// Return the parameters of the effect, if any.
178  Attribute getParameters() const { return parameters; }
179 
180 private:
181  /// The specific effect being applied.
182  EffectT *effect;
183 
184  /// The resource that the given value resides in.
185  Resource *resource;
186 
187  /// The Symbol or Value that the effect applies to. This is optionally null.
189 
190  /// Additional parameters of the effect instance. An attribute is used for
191  /// type-safe structured storage and context-based uniquing. Concrete effects
192  /// can use this at their convenience. This is optionally null.
193  Attribute parameters;
194 };
195 } // namespace SideEffects
196 
197 namespace Speculation {
198 /// This enum is returned from the `getSpeculatability` method in the
199 /// `ConditionallySpeculatable` op interface.
200 enum class Speculatability {
201  /// The Operation in question cannot be speculatively executed. This could be
202  /// because it may invoke undefined behavior or have other side effects.
204 
205  // The Operation in question can be speculatively executed. It does not have
206  // any side effects or undefined behavior.
207  Speculatable,
208 
209  // The Operation in question can be speculatively executed if all the
210  // operations in all attached regions can also be speculatively executed.
212 };
213 
216 constexpr auto RecursivelySpeculatable =
218 } // namespace Speculation
219 
220 //===----------------------------------------------------------------------===//
221 // SideEffect Traits
222 //===----------------------------------------------------------------------===//
223 
224 namespace OpTrait {
225 /// This trait indicates that the memory effects of an operation includes the
226 /// effects of operations nested within its regions. If the operation has no
227 /// derived effects interfaces, the operation itself can be assumed to have no
228 /// memory effects.
229 template <typename ConcreteType>
231  : public TraitBase<ConcreteType, HasRecursiveMemoryEffects> {};
232 
233 /// This trait marks an op (which must be tagged as implementing the
234 /// ConditionallySpeculatable interface) as being recursively speculatable.
235 /// This means that said op can be speculated only if all the instructions in
236 /// all the regions attached to the op can be speculated.
237 template <typename ConcreteType>
239  : public TraitBase<ConcreteType, RecursivelySpeculatableImplTrait> {
240 
243  }
244 };
245 
246 /// This trait marks an op (which must be tagged as implementing the
247 /// ConditionallySpeculatable interface) as being always speculatable.
248 template <typename ConcreteType>
250  : public TraitBase<ConcreteType, AlwaysSpeculatableImplTrait> {
251 
254  }
255 };
256 } // namespace OpTrait
257 
258 //===----------------------------------------------------------------------===//
259 // Operation Memory-Effect Modeling
260 //===----------------------------------------------------------------------===//
261 
262 namespace MemoryEffects {
263 /// This class represents the base class used for memory effects.
264 struct Effect : public SideEffects::Effect {
266 
267  /// A base class for memory effects that provides helper utilities.
268  template <typename DerivedEffect>
270 
271  static bool classof(const SideEffects::Effect *effect);
272 };
274 
275 /// The following effect indicates that the operation allocates from some
276 /// resource. An 'allocate' effect implies only allocation of the resource, and
277 /// not any visible mutation or dereference.
278 struct Allocate : public Effect::Base<Allocate> {};
279 
280 /// The following effect indicates that the operation frees some resource that
281 /// has been allocated. An 'allocate' effect implies only de-allocation of the
282 /// resource, and not any visible allocation, mutation or dereference.
283 struct Free : public Effect::Base<Free> {};
284 
285 /// The following effect indicates that the operation reads from some resource.
286 /// A 'read' effect implies only dereferencing of the resource, and not any
287 /// visible mutation.
288 struct Read : public Effect::Base<Read> {};
289 
290 /// The following effect indicates that the operation writes to some resource. A
291 /// 'write' effect implies only mutating a resource, and not any visible
292 /// dereference or read.
293 struct Write : public Effect::Base<Write> {};
294 } // namespace MemoryEffects
295 
296 //===----------------------------------------------------------------------===//
297 // SideEffect Utilities
298 //===----------------------------------------------------------------------===//
299 
300 /// Returns true if `op` has only an effect of type `EffectTy` (and of no other
301 /// type) on `value`. If no value is provided, simply check if effects of that
302 /// type and only of that type are present.
303 template <typename EffectTy>
304 bool hasSingleEffect(Operation *op, Value value = nullptr);
305 
306 /// Returns true if `op` has an effect of type `EffectTy` on `value`. If no
307 /// `value` is provided, simply check if effects of the given type(s) are
308 /// present.
309 template <typename... EffectTys>
310 bool hasEffect(Operation *op, Value value = nullptr);
311 
312 /// Return true if the given operation is unused, and has no side effects on
313 /// memory that prevent erasing.
314 bool isOpTriviallyDead(Operation *op);
315 
316 /// Return true if the given operation would be dead if unused, and has no side
317 /// effects on memory that would prevent erasing. This is equivalent to checking
318 /// `isOpTriviallyDead` if `op` was unused.
320 
321 /// Returns true if the given operation is free of memory effects.
322 ///
323 /// An operation is free of memory effects if its implementation of
324 /// `MemoryEffectOpInterface` indicates that it has no memory effects. For
325 /// example, it may implement `NoMemoryEffect` in ODS. Alternatively, if the
326 /// operation has the `HasRecursiveMemoryEffects` trait, then it is free of
327 /// memory effects if all of its nested operations are free of memory effects.
328 ///
329 /// If the operation has both, then it is free of memory effects if both
330 /// conditions are satisfied.
331 bool isMemoryEffectFree(Operation *op);
332 
333 /// Returns true if the given operation is speculatable, i.e. has no undefined
334 /// behavior or other side effects.
335 ///
336 /// An operation can indicate that it is speculatable by implementing the
337 /// getSpeculatability hook in the ConditionallySpeculatable op interface.
338 bool isSpeculatable(Operation *op);
339 
340 /// Returns true if the given operation is pure, i.e., is speculatable that does
341 /// not touch memory.
342 ///
343 /// This function is the C++ equivalent of the `Pure` trait.
344 bool isPure(Operation *op);
345 
346 } // namespace mlir
347 
348 //===----------------------------------------------------------------------===//
349 // SideEffect Interfaces
350 //===----------------------------------------------------------------------===//
351 
352 /// Include the definitions of the side effect interfaces.
353 #include "mlir/Interfaces/SideEffectInterfaces.h.inc"
354 
355 #endif // MLIR_INTERFACES_SIDEEFFECTINTERFACES_H
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This trait indicates that the memory effects of an operation includes the effects of operations neste...
Helper class for implementing traits.
Definition: OpDefinition.h:310
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
This class represents a specific instance of an effect.
EffectInstance(EffectT *effect, Value value, Attribute parameters, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, Value value, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, SymbolRefAttr symbol, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, Resource *resource=DefaultResource::get())
SymbolRefAttr getSymbolRef() const
Return the symbol reference the effect is applied on, or nullptr if there isn't a known smbol being a...
EffectInstance(EffectT *effect, Attribute parameters, Resource *resource=DefaultResource::get())
Resource * getResource() const
Return the resource that the effect applies to.
Attribute getParameters() const
Return the parameters of the effect, if any.
EffectT * getEffect() const
Return the effect being applied.
Value getValue() const
Return the value the effect is applied on, or nullptr if there isn't a known value being affected.
This base class is used for derived effects that are non-parametric.
static TypeID getEffectID()
Return the unique identifier for the base effects class.
static bool classof(const ::mlir::SideEffects::Effect *effect)
'classof' used to support llvm style cast functionality.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
This class represents a base class for a specific effect type.
TypeID getEffectID() const
Return the unique identifier for the base effects class.
static DerivedEffect * get()
Returns a unique instance for the given effect class.
This base class is used for derived effects that are non-parametric.
static DerivedResource * get()
Returns a unique instance for the given effect class.
static TypeID getResourceID()
Return the unique identifier for the base resource class.
static bool classof(const Resource *resource)
'classof' used to support llvm style cast functionality.
This class represents a specific resource that an effect applies to.
TypeID getResourceID() const
Return the unique identifier for the base resource class.
virtual StringRef getName()=0
Return a string name of the resource.
virtual ~Resource()=default
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
U dyn_cast() const
Definition: Value.h:103
constexpr auto RecursivelySpeculatable
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
@ NotSpeculatable
The Operation in question cannot be speculatively executed.
constexpr auto Speculatable
constexpr auto NotSpeculatable
Include the generated interface declarations.
bool hasEffect(Operation *op, Value value=nullptr)
Returns true if op has an effect of type EffectTy on value.
bool isPure(Operation *op)
Returns true if the given operation is pure, i.e., is speculatable that does not touch memory.
bool isMemoryEffectFree(Operation *op)
Returns true if the given operation is free of memory effects.
bool wouldOpBeTriviallyDead(Operation *op)
Return true if the given operation would be dead if unused, and has no side effects on memory that wo...
bool hasSingleEffect(Operation *op, Value value=nullptr)
Returns true if op has only an effect of type EffectTy (and of no other type) on value.
bool isSpeculatable(Operation *op)
Returns true if the given operation is speculatable, i.e.
bool isOpTriviallyDead(Operation *op)
Return true if the given operation is unused, and has no side effects on memory that prevent erasing.
The following effect indicates that the operation allocates from some resource.
This class represents the base class used for memory effects.
static bool classof(const SideEffects::Effect *effect)
Include the definitions of the side effect interfaces.
The following effect indicates that the operation frees some resource that has been allocated.
The following effect indicates that the operation reads from some resource.
The following effect indicates that the operation writes to some resource.
This trait marks an op (which must be tagged as implementing the ConditionallySpeculatable interface)...
Speculation::Speculatability getSpeculatability()
This trait marks an op (which must be tagged as implementing the ConditionallySpeculatable interface)...
An automatic allocation-scope resource that is valid in the context of a parent AutomaticAllocationSc...
StringRef getName() final
Return a string name of the resource.
A conservative default resource kind.
StringRef getName() final
Return a string name of the resource.