MLIR 22.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
18
19namespace mlir {
20namespace SideEffects {
21//===----------------------------------------------------------------------===//
22// Effects
23//===----------------------------------------------------------------------===//
24
25/// This class represents a base class for a specific effect type.
26class Effect {
27public:
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.
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
65protected:
66 Effect(TypeID id) : id(id) {}
67
68private:
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.
79class Resource {
80public:
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.
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
113protected:
114 Resource(TypeID id) : id(id) {}
115
116private:
117 /// The id of the derived resource class.
118 TypeID id;
119};
120
121/// A conservative default resource kind.
122struct 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.
138template <typename EffectT>
140public:
141 EffectInstance(EffectT *effect, Resource *resource = DefaultResource::get())
142 : effect(effect), resource(resource), stage(0),
143 effectOnFullRegion(false) {}
144 EffectInstance(EffectT *effect, int stage, bool effectOnFullRegion,
145 Resource *resource = DefaultResource::get())
146 : effect(effect), resource(resource), stage(stage),
147 effectOnFullRegion(effectOnFullRegion) {}
148 template <typename T,
149 std::enable_if_t<
150 llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
151 bool> = true>
152 EffectInstance(EffectT *effect, T value,
153 Resource *resource = DefaultResource::get())
154 : effect(effect), resource(resource), value(value), stage(0),
155 effectOnFullRegion(false) {}
156 template <typename T,
157 std::enable_if_t<
158 llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
159 bool> = true>
160 EffectInstance(EffectT *effect, T value, int stage, bool effectOnFullRegion,
161 Resource *resource = DefaultResource::get())
162 : effect(effect), resource(resource), value(value), stage(stage),
163 effectOnFullRegion(effectOnFullRegion) {}
164 EffectInstance(EffectT *effect, SymbolRefAttr symbol,
165 Resource *resource = DefaultResource::get())
166 : effect(effect), resource(resource), value(symbol), stage(0),
167 effectOnFullRegion(false) {}
168 EffectInstance(EffectT *effect, SymbolRefAttr symbol, int stage,
169 bool effectOnFullRegion,
170 Resource *resource = DefaultResource::get())
171 : effect(effect), resource(resource), value(symbol), stage(stage),
172 effectOnFullRegion(effectOnFullRegion) {}
173 EffectInstance(EffectT *effect, Attribute parameters,
174 Resource *resource = DefaultResource::get())
175 : effect(effect), resource(resource), parameters(parameters), stage(0),
176 effectOnFullRegion(false) {}
177 EffectInstance(EffectT *effect, Attribute parameters, int stage,
178 bool effectOnFullRegion,
179 Resource *resource = DefaultResource::get())
180 : effect(effect), resource(resource), parameters(parameters),
181 stage(stage), effectOnFullRegion(effectOnFullRegion) {}
182 template <typename T,
183 std::enable_if_t<
184 llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
185 bool> = true>
186 EffectInstance(EffectT *effect, T value, Attribute parameters,
187 Resource *resource = DefaultResource::get())
188 : effect(effect), resource(resource), value(value),
189 parameters(parameters), stage(0), effectOnFullRegion(false) {}
190 template <typename T,
191 std::enable_if_t<
192 llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
193 bool> = true>
194 EffectInstance(EffectT *effect, T value, Attribute parameters, int stage,
195 bool effectOnFullRegion,
196 Resource *resource = DefaultResource::get())
197 : effect(effect), resource(resource), value(value),
198 parameters(parameters), stage(stage),
199 effectOnFullRegion(effectOnFullRegion) {}
200 EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters,
201 Resource *resource = DefaultResource::get())
202 : effect(effect), resource(resource), value(symbol),
203 parameters(parameters), stage(0), effectOnFullRegion(false) {}
204 EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters,
205 int stage, bool effectOnFullRegion,
206 Resource *resource = DefaultResource::get())
207 : effect(effect), resource(resource), value(symbol),
208 parameters(parameters), stage(stage),
209 effectOnFullRegion(effectOnFullRegion) {}
210
211 /// Return the effect being applied.
212 EffectT *getEffect() const { return effect; }
213
214 /// Return the value the effect is applied on, or nullptr if there isn't a
215 /// known value being affected.
216 Value getValue() const {
217 if (!value || llvm::isa_and_present<SymbolRefAttr>(value)) {
218 return Value();
219 }
220 if (OpOperand *operand = llvm::dyn_cast_if_present<OpOperand *>(value)) {
221 return operand->get();
222 }
223 if (OpResult result = llvm::dyn_cast_if_present<OpResult>(value)) {
224 return result;
225 }
226 return cast_if_present<BlockArgument>(value);
227 }
228
229 /// Returns the OpOperand effect is applied on, or nullptr if there isn't a
230 /// known value being effected.
231 template <typename T,
232 std::enable_if_t<
233 llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
234 bool> = true>
235 T getEffectValue() const {
236 return value ? dyn_cast_if_present<T>(value) : nullptr;
237 }
238
239 /// Return the symbol reference the effect is applied on, or nullptr if there
240 /// isn't a known smbol being affected.
241 SymbolRefAttr getSymbolRef() const {
242 return value ? llvm::dyn_cast_if_present<SymbolRefAttr>(value)
243 : SymbolRefAttr();
244 }
245
246 /// Return the resource that the effect applies to.
247 Resource *getResource() const { return resource; }
248
249 /// Return the parameters of the effect, if any.
250 Attribute getParameters() const { return parameters; }
251
252 /// Return the effect happen stage.
253 int getStage() const { return stage; }
254
255 /// Return if this side effect act on every single value of resource.
256 bool getEffectOnFullRegion() const { return effectOnFullRegion; }
257
258private:
259 /// The specific effect being applied.
260 EffectT *effect;
261
262 /// The resource that the given value resides in.
263 Resource *resource;
264
265 /// The Symbol, OpOperand, OpResult or BlockArgument that the effect applies
266 /// to. This is optionally null.
268
269 /// Additional parameters of the effect instance. An attribute is used for
270 /// type-safe structured storage and context-based uniquing. Concrete effects
271 /// can use this at their convenience. This is optionally null.
272 Attribute parameters;
273
274 // The stage side effect happen. Side effect with a lower stage
275 // number happen earlier than those with a higher stage number
276 int stage;
277
278 // Does this side effect act on every single value of resource.
279 bool effectOnFullRegion;
280};
281} // namespace SideEffects
282
283namespace Speculation {
284/// This enum is returned from the `getSpeculatability` method in the
285/// `ConditionallySpeculatable` op interface.
286enum class Speculatability {
287 /// The Operation in question cannot be speculatively executed. This could be
288 /// because it may invoke undefined behavior or have other side effects.
290
291 // The Operation in question can be speculatively executed. It does not have
292 // any side effects or undefined behavior.
294
295 // The Operation in question can be speculatively executed if all the
296 // operations in all attached regions can also be speculatively executed.
298};
299
304} // namespace Speculation
305
306//===----------------------------------------------------------------------===//
307// SideEffect Traits
308//===----------------------------------------------------------------------===//
309
310namespace OpTrait {
311/// This trait indicates that the memory effects of an operation includes the
312/// effects of operations nested within its regions. If the operation has no
313/// derived effects interfaces, the operation itself can be assumed to have no
314/// memory effects.
315template <typename ConcreteType>
317 : public TraitBase<ConcreteType, HasRecursiveMemoryEffects> {};
318
319/// This trait marks an op (which must be tagged as implementing the
320/// ConditionallySpeculatable interface) as being recursively speculatable.
321/// This means that said op can be speculated only if all the instructions in
322/// all the regions attached to the op can be speculated.
323template <typename ConcreteType>
325 : public TraitBase<ConcreteType, RecursivelySpeculatableImplTrait> {
326
330};
331
332/// This trait marks an op (which must be tagged as implementing the
333/// ConditionallySpeculatable interface) as being always speculatable.
334template <typename ConcreteType>
336 : public TraitBase<ConcreteType, AlwaysSpeculatableImplTrait> {
337
341};
342} // namespace OpTrait
343
344//===----------------------------------------------------------------------===//
345// Operation Memory-Effect Modeling
346//===----------------------------------------------------------------------===//
347
348namespace MemoryEffects {
349/// This class represents the base class used for memory effects.
352
353 /// A base class for memory effects that provides helper utilities.
354 template <typename DerivedEffect>
356
357 static bool classof(const SideEffects::Effect *effect);
358};
360
361/// The following effect indicates that the operation allocates from some
362/// resource. An 'allocate' effect implies only allocation of the resource, and
363/// not any visible mutation or dereference.
364struct Allocate : public Effect::Base<Allocate> {};
365
366/// The following effect indicates that the operation frees some resource that
367/// has been allocated. An 'allocate' effect implies only de-allocation of the
368/// resource, and not any visible allocation, mutation or dereference.
369struct Free : public Effect::Base<Free> {};
370
371/// The following effect indicates that the operation reads from some resource.
372/// A 'read' effect implies only dereferencing of the resource, and not any
373/// visible mutation.
374struct Read : public Effect::Base<Read> {};
375
376/// The following effect indicates that the operation writes to some resource. A
377/// 'write' effect implies only mutating a resource, and not any visible
378/// dereference or read.
379struct Write : public Effect::Base<Write> {};
380} // namespace MemoryEffects
381
382//===----------------------------------------------------------------------===//
383// SideEffect Utilities
384//===----------------------------------------------------------------------===//
385
386/// Return "true" if `op` has unknown effects. I.e., the effects of the
387/// operation itself are unknown and the operation does not derive its effects
388/// from its nested operations. (`HasRecursiveMemoryEffects` trait is not
389/// implemented or it is unknown whether it is implemented or not.)
391
392/// Returns "true" if `op` has only an effect of type `EffectTy`. Returns
393/// "false" if `op` has unknown effects or other/additional effects. Recursive
394/// effects are not taken into account.
395template <typename EffectTy>
396bool hasSingleEffect(Operation *op);
397
398/// Returns "true" if `op` has only an effect of type `EffectTy` on `value`.
399/// Returns "false" if `op` has unknown effects or other/additional effects.
400/// Recursive effects are not taken into account.
401template <typename EffectTy>
402bool hasSingleEffect(Operation *op, Value value);
403
404/// Returns "true" if `op` has only an effect of type `EffectTy` on `value` of
405/// type `ValueTy`. Returns "false" if `op` has unknown effects or
406/// other/additional effects. Recursive effects are not taken into account.
407template <typename ValueTy, typename EffectTy>
408bool hasSingleEffect(Operation *op, ValueTy value);
409
410/// Returns "true" if `op` has an effect of type `EffectTy`. Returns "false" if
411/// `op` has unknown effects. Recursive effects are not taken into account.
412template <typename... EffectTys>
413bool hasEffect(Operation *op);
414
415/// Returns "true" if `op` has an effect of type `EffectTy` on `value`. Returns
416/// "false" if `op` has unknown effects. Recursive effects are not taken into
417/// account.
418template <typename... EffectTys>
419bool hasEffect(Operation *op, Value value);
420
421/// Returns "true" if `op` has an effect of type `EffectTy` on `value` of type
422/// `ValueTy`. Returns "false" if `op` has unknown effects. Recursive effects
423/// are not taken into account.
424template <typename ValueTy, typename... EffectTys>
425bool hasEffect(Operation *op, ValueTy value);
426
427/// Returns "true" if `op` might have an effect of type `EffectTy`. Returns
428/// "true" if the op has unknown effects. Recursive effects are not taken into
429/// account.
430template <typename... EffectTys>
432 return hasUnknownEffects(op) || hasEffect<EffectTys...>(op);
433}
434
435/// Returns "true" if `op` might have an effect of type `EffectTy` on `value`.
436/// Returns "true" if the op has unknown effects. Recursive effects are not
437/// taken into account.
438template <typename... EffectTys>
440 return hasUnknownEffects(op) || hasEffect<EffectTys...>(op, value);
441}
442
443/// Returns "true" if `op` might have an effect of type `EffectTy` on `value`
444/// of type `ValueTy`. Returns "true" if the op has unknown effects. Recursive
445/// effects are not taken into account.
446template <typename ValueTy, typename... EffectTys>
447bool mightHaveEffect(Operation *op, ValueTy value) {
448 return hasUnknownEffects(op) || hasEffect<EffectTys...>(op, value);
449}
450
451/// Return true if the given operation is unused, and has no side effects on
452/// memory that prevent erasing.
453bool isOpTriviallyDead(Operation *op);
454
455/// Return true if the given operation would be dead if unused, and has no side
456/// effects on memory that would prevent erasing. This is equivalent to checking
457/// `isOpTriviallyDead` if `op` was unused.
458///
459/// Note: Terminators and symbols are never considered to be trivially dead.
460bool wouldOpBeTriviallyDead(Operation *op);
461
462/// Returns true if the given operation is free of memory effects.
463///
464/// An operation is free of memory effects if its implementation of
465/// `MemoryEffectOpInterface` indicates that it has no memory effects. For
466/// example, it may implement `NoMemoryEffect` in ODS. Alternatively, if the
467/// operation has the `HasRecursiveMemoryEffects` trait, then it is free of
468/// memory effects if all of its nested operations are free of memory effects.
469///
470/// If the operation has both, then it is free of memory effects if both
471/// conditions are satisfied.
472bool isMemoryEffectFree(Operation *op);
473
474/// Returns the side effects of an operation. If the operation has
475/// RecursiveMemoryEffects, include all side effects of child operations.
476///
477/// std::nullopt indicates that an option did not have a memory effect interface
478/// and so no result could be obtained. An empty vector indicates that there
479/// were no memory effects found (but every operation implemented the memory
480/// effect interface or has RecursiveMemoryEffects). If the vector contains
481/// multiple effects, these effects may be duplicates.
482std::optional<llvm::SmallVector<MemoryEffects::EffectInstance>>
483getEffectsRecursively(Operation *rootOp);
484
485/// Returns true if the given operation is speculatable, i.e. has no undefined
486/// behavior or other side effects.
487///
488/// An operation can indicate that it is speculatable by implementing the
489/// getSpeculatability hook in the ConditionallySpeculatable op interface.
490bool isSpeculatable(Operation *op);
491
492/// Returns true if the given operation is pure, i.e., is speculatable that does
493/// not touch memory.
494///
495/// This function is the C++ equivalent of the `Pure` trait.
496bool isPure(Operation *op);
497
498} // namespace mlir
499
500//===----------------------------------------------------------------------===//
501// SideEffect Interfaces
502//===----------------------------------------------------------------------===//
503
504/// Include the definitions of the side effect interfaces.
505#include "mlir/Interfaces/SideEffectInterfaces.h.inc"
506
507#endif // MLIR_INTERFACES_SIDEEFFECTINTERFACES_H
false
Parses a map_entries map type from a string format back into its numeric value.
Attributes are known-constant values of operations.
Definition Attributes.h:25
This class represents an operand of an operation.
Definition Value.h:257
This is a value defined by a result of an operation.
Definition Value.h:457
This trait indicates that the memory effects of an operation includes the effects of operations neste...
Helper class for implementing traits.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class represents a specific instance of an effect.
Resource * getResource() const
Return the resource that the effect applies to.
EffectT * getEffect() const
Return the effect being applied.
EffectInstance(EffectT *effect, T value, Attribute parameters, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, T value, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters, int stage, bool effectOnFullRegion, Resource *resource=DefaultResource::get())
bool getEffectOnFullRegion() const
Return if this side effect act on every single value of resource.
int getStage() const
Return the effect happen stage.
EffectInstance(EffectT *effect, SymbolRefAttr symbol, Attribute parameters, Resource *resource=DefaultResource::get())
T getEffectValue() const
Returns the OpOperand effect is applied on, or nullptr if there isn't a known value being effected.
EffectInstance(EffectT *effect, SymbolRefAttr symbol, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, T value, int stage, bool effectOnFullRegion, 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, int stage, bool effectOnFullRegion, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, Attribute parameters, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, T value, Attribute parameters, int stage, bool effectOnFullRegion, Resource *resource=DefaultResource::get())
Attribute getParameters() const
Return the parameters of the effect, if any.
Value getValue() const
Return the value the effect is applied on, or nullptr if there isn't a known value being affected.
EffectInstance(EffectT *effect, Attribute parameters, int stage, bool effectOnFullRegion, Resource *resource=DefaultResource::get())
EffectInstance(EffectT *effect, SymbolRefAttr symbol, int stage, bool effectOnFullRegion, Resource *resource=DefaultResource::get())
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 DerivedEffect * get()
Returns a unique instance for the derived effect class.
static bool classof(const ::mlir::SideEffects::Effect *effect)
'classof' used to support llvm style cast functionality.
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:107
static TypeID get()
Construct a type info object for the given type T.
Definition TypeID.h:245
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
SideEffects::EffectInstance< Effect > EffectInstance
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 hasSingleEffect(Operation *op)
Returns "true" if op has only an effect of type EffectTy.
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 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.
std::optional< llvm::SmallVector< MemoryEffects::EffectInstance > > getEffectsRecursively(Operation *rootOp)
Returns the side effects of an operation.
bool hasEffect(Operation *op)
Returns "true" if op has an effect of type EffectTy.
bool hasUnknownEffects(Operation *op)
Return "true" if op has unknown effects.
bool mightHaveEffect(Operation *op)
Returns "true" if op might have an effect of type EffectTy.
The following effect indicates that the operation allocates from some resource.
SideEffects::Effect::Base< DerivedEffect, Effect > Base
A base class for memory effects that provides helper utilities.
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.