MLIR  14.0.0git
SideEffectInterfaces.cpp
Go to the documentation of this file.
1 //===- SideEffectInterfaces.cpp - SideEffects in MLIR ---------------------===//
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 
10 
11 using namespace mlir;
12 
13 //===----------------------------------------------------------------------===//
14 // SideEffect Interfaces
15 //===----------------------------------------------------------------------===//
16 
17 /// Include the definitions of the side effect interfaces.
18 #include "mlir/Interfaces/SideEffectInterfaces.cpp.inc"
19 
20 //===----------------------------------------------------------------------===//
21 // MemoryEffects
22 //===----------------------------------------------------------------------===//
23 
25  return isa<Allocate, Free, Read, Write>(effect);
26 }
27 
28 //===----------------------------------------------------------------------===//
29 // SideEffect Utilities
30 //===----------------------------------------------------------------------===//
31 
33  return op->use_empty() && wouldOpBeTriviallyDead(op);
34 }
35 
36 /// Internal implementation of `mlir::wouldOpBeTriviallyDead` that also
37 /// considers terminator operations as dead if they have no side effects. This
38 /// allows for marking region operations as trivially dead without always being
39 /// conservative of terminators.
40 static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp) {
41  // The set of operations to consider when checking for side effects.
42  SmallVector<Operation *, 1> effectingOps(1, rootOp);
43  while (!effectingOps.empty()) {
44  Operation *op = effectingOps.pop_back_val();
45 
46  // If the operation has recursive effects, push all of the nested operations
47  // on to the stack to consider.
48  bool hasRecursiveEffects = op->hasTrait<OpTrait::HasRecursiveSideEffects>();
49  if (hasRecursiveEffects) {
50  for (Region &region : op->getRegions()) {
51  for (auto &block : region) {
52  for (auto &nestedOp : block)
53  effectingOps.push_back(&nestedOp);
54  }
55  }
56  }
57 
58  // If the op has memory effects, try to characterize them to see if the op
59  // is trivially dead here.
60  if (auto effectInterface = dyn_cast<MemoryEffectOpInterface>(op)) {
61  // Check to see if this op either has no effects, or only allocates/reads
62  // memory.
64  effectInterface.getEffects(effects);
65  if (!llvm::all_of(effects, [op](const MemoryEffects::EffectInstance &it) {
66  // We can drop allocations if the value is a result of the
67  // operation.
68  if (isa<MemoryEffects::Allocate>(it.getEffect()))
69  return it.getValue() && it.getValue().getDefiningOp() == op;
70  // Otherwise, the effect must be a read.
71  return isa<MemoryEffects::Read>(it.getEffect());
72  })) {
73  return false;
74  }
75  continue;
76 
77  // Otherwise, if the op has recursive side effects we can treat the
78  // operation itself as having no effects.
79  }
80  if (hasRecursiveEffects)
81  continue;
82 
83  // If there were no effect interfaces, we treat this op as conservatively
84  // having effects.
85  return false;
86  }
87 
88  // If we get here, none of the operations had effects that prevented marking
89  // 'op' as dead.
90  return true;
91 }
92 
95  return false;
96  return wouldOpBeTriviallyDeadImpl(op);
97 }
Include the generated interface declarations.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
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 isOpTriviallyDead(Operation *op)
Return true if the given operation is unused, and has no side effects on memory that prevent erasing...
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:423
EffectT * getEffect() const
Return the effect being applied.
Value getValue() const
Return the value the effect is applied on, or nullptr if there isn&#39;t a known value being affected...
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition: Operation.h:477
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:706
This trait indicates that the side effects of an operation includes the effects of operations nested ...
static bool classof(const SideEffects::Effect *effect)
Include the definitions of the side effect interfaces.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:470
This class represents a specific instance of an effect.
bool use_empty()
Returns true if this operation has no uses.
Definition: Operation.h:570
This class represents a base class for a specific effect type.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:20
static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp)
Internal implementation of mlir::wouldOpBeTriviallyDead that also considers terminator operations as ...