21 #include "llvm/Support/DebugLog.h"
23 #define DEBUG_TYPE "optimize-allocation-liveness"
26 namespace bufferization {
27 #define GEN_PASS_DEF_OPTIMIZEALLOCATIONLIVENESSPASS
28 #include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
58 if (MemoryEffectOpInterface memEffectOp =
59 dyn_cast<MemoryEffectOpInterface>(user)) {
61 memEffectOp.getEffects(effects);
63 for (
const auto &effect : effects) {
64 if (isa<MemoryEffects::Free>(effect.getEffect())) {
66 LDBG() <<
"Multiple users with free effect found: " << *freeOpUser
79 static bool hasMemoryAllocEffect(MemoryEffectOpInterface memEffectOp) {
81 memEffectOp.getEffects(effects);
82 for (
const auto &effect : effects) {
83 if (isa<MemoryEffects::Allocate>(effect.getEffect())) {
92 collectAllocations(MemoryEffectOpInterface allocOp) {
94 allocOp.getEffects(effects);
97 if (isa<MemoryEffects::Allocate>(it.getEffect()))
98 if (
auto val = it.getValue(); val && val.getDefiningOp() == allocOp)
99 allocResults.push_back(cast<OpResult>(val));
103 struct OptimizeAllocationLiveness
104 :
public bufferization::impl::OptimizeAllocationLivenessPassBase<
105 OptimizeAllocationLiveness> {
107 OptimizeAllocationLiveness() =
default;
109 void runOnOperation()
override {
110 func::FuncOp func = getOperation();
112 if (func.isExternal())
117 func.walk([&](MemoryEffectOpInterface memEffectOp) ->
WalkResult {
118 if (!hasMemoryAllocEffect(memEffectOp))
121 auto allocOp = memEffectOp;
122 LDBG() <<
"Checking alloc op: " << allocOp;
126 if (allocationResults.size() != 1)
129 OpResult allocResult = allocationResults[0];
130 LDBG() <<
"On allocation result: " << allocResult;
132 auto *deallocOp = findUserWithFreeSideEffect(allocResult);
133 if (!deallocOp || (deallocOp->getBlock() != allocOp->getBlock())) {
143 for (
auto dep : llvm::make_early_inc_range(deps)) {
144 for (
auto *user : dep.getUsers()) {
147 if (user == deallocOp)
151 auto topUser = allocOp->getBlock()->findAncestorOpInBlock(*user);
157 if (lastUser ==
nullptr) {
160 LDBG() <<
"Last user found: " << *lastUser;
161 assert(lastUser->
getBlock() == allocOp->getBlock());
162 assert(lastUser->
getBlock() == deallocOp->getBlock());
164 deallocOp->moveAfter(lastUser);
165 LDBG() <<
"Moved dealloc op after: " << *lastUser;
static bool happensBefore(Operation *a, Operation *b, const DominanceInfo &domInfo)
Return true if a happens before b, i.e., a or one of its ancestors properly dominates b and b is not ...
Operation * findAncestorOpInBlock(Operation &op)
Returns 'op' if 'op' lies in this block, or otherwise finds the ancestor operation of 'op' that lies ...
A straight-forward alias analysis which ensures that all dependencies of all values will be determine...
This is a value defined by a result of an operation.
Operation is the basic unit of execution within MLIR.
bool isBeforeInBlock(Operation *other)
Given an operation 'other' that is within the same parent block, return whether the current operation...
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Block * getBlock()
Returns the operation block that contains this operation.
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
This class represents a specific instance of an effect.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
user_range getUsers() const
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
Include the generated interface declarations.