21#include "mlir/Interfaces/SideEffectInterfaces.cpp.inc"
28 return isa<Allocate, Free, Read, Write>(effect);
50 if (
auto effectInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
52 effectInterface.getEffects(effects);
57 if (isa<MemoryEffects::Allocate>(effect.getEffect()) &&
58 effect.getValue() && effect.getValue().getDefiningOp() == op)
59 allocResults.insert(effect.getValue());
60 return llvm::all_of(effects,
65 return allocResults.contains(effect.
getValue()) ||
66 isa<MemoryEffects::Read>(effect.
getEffect());
69 return hasRecursiveEffects;
93 while (!worklist.empty()) {
94 WorkItem &item = worklist.back();
95 if (item.current == item.end) {
96 if (cache && item.complete)
97 (*cache)[item.complete] = State::Dead;
102 bool cachedAlive =
false;
104 auto cached = cache->find(op);
105 if (cached != cache->end()) {
106 if (cached->second == State::Dead)
117 (*cache)[ancestor] = State::Alive;
118 if (ancestor == root)
126 (*cache)[op] = State::Dead;
131 Operation *complete = cache ? op :
nullptr;
133 for (
Block &block : region) {
134 worklist.push_back({block.begin(), block.end(), complete});
139 (*cache)[complete] = State::Dead;
149 isa<SymbolOpInterface>(root))
152 auto cachedRoot = cache.find(root);
153 if (cachedRoot != cache.end())
172template <
typename EffectTy>
174 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
178 memOp.getEffects(effects);
179 bool hasSingleEffectOnVal =
false;
182 for (
auto &effect : effects) {
183 hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
184 if (!hasSingleEffectOnVal)
187 return hasSingleEffectOnVal;
194template <
typename EffectTy>
196 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
200 memOp.getEffects(effects);
201 bool hasSingleEffectOnVal =
false;
204 for (
auto &effect : effects) {
205 if (effect.getValue() != value)
207 hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
208 if (!hasSingleEffectOnVal)
211 return hasSingleEffectOnVal;
223template <
typename ValueTy,
typename EffectTy>
225 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
229 memOp.getEffects(effects);
230 bool hasSingleEffectOnVal =
false;
233 for (
auto &effect : effects) {
234 if (effect.getEffectValue<ValueTy>() != value)
236 hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
237 if (!hasSingleEffectOnVal)
240 return hasSingleEffectOnVal;
276template <
typename... EffectTys>
278 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
282 memOp.getEffects(effects);
284 return isa<EffectTys...>(effect.
getEffect());
294template <
typename... EffectTys>
296 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
300 memOp.getEffects(effects);
304 return isa<EffectTys...>(effect.
getEffect());
316template <
typename ValueTy,
typename... EffectTys>
318 auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
322 memOp.getEffects(effects);
326 return isa<EffectTys...>(effect.
getEffect());
368 return !isa<MemoryEffectOpInterface>(op) &&
375 if (isa<SymbolOpInterface>(op))
381 if (
auto memInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
382 if (!memInterface.hasNoEffect())
405std::optional<llvm::SmallVector<MemoryEffects::EffectInstance>>
409 while (!effectingOps.empty()) {
410 Operation *op = effectingOps.pop_back_val();
414 bool hasRecursiveEffects =
416 if (hasRecursiveEffects) {
418 for (
Block &block : region) {
420 effectingOps.push_back(&nestedOp);
426 if (
auto effectInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
427 effectInterface.getEffects(effects);
428 }
else if (!hasRecursiveEffects) {
438 auto conditionallySpeculatable = dyn_cast<ConditionallySpeculatable>(op);
439 if (!conditionallySpeculatable)
442 switch (conditionallySpeculatable.getSpeculatability()) {
458 llvm_unreachable(
"Unhandled enum in mlir::isSpeculatable!");
static bool hasOnlyRemovableEffects(Operation *op, bool hasRecursiveEffects)
Return true if the op's own memory effects do not prevent erasure.
static bool wouldOpBeTriviallyDeadImpl(Operation *root, DenseMap< Operation *, DeadnessCache::State > *cache=nullptr)
Internal implementation of mlir::wouldOpBeTriviallyDead that also considers terminator operations as ...
This class represents an argument of a Block.
Block represents an ordered list of Operations.
OpListType::iterator iterator
bool isOpTriviallyDead(Operation *op)
Return true if the operation is unused and can be erased.
void invalidateAncestors(Operation *op)
Invalidate the operation and its ancestors, preserving descendant entries.
void invalidate(Operation *op)
Invalidate the operation, its descendants, and its ancestors.
This class represents an operand of an operation.
This is a value defined by a result of an operation.
This trait indicates that the memory effects of an operation includes the effects of operations neste...
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
bool use_empty()
Returns true if this operation has no uses.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
EffectT * getEffect() const
Return the effect being applied.
T getEffectValue() const
Returns the OpOperand effect is applied on, or nullptr if there isn't a known value being effected.
Value getValue() const
Return the value the effect is applied on, or nullptr if there isn't a known value being affected.
This class represents a base class for a specific effect type.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
SideEffects::EffectInstance< Effect > EffectInstance
constexpr auto RecursivelySpeculatable
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.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
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.
static bool classof(const SideEffects::Effect *effect)
Include the definitions of the side effect interfaces.