20 #include "llvm/Support/Debug.h"
22 #define DEBUG_TYPE "optimize-allocation-liveness"
23 #define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
24 #define LDBG(X) LLVM_DEBUG(DBGS() << X << "\n")
27 namespace bufferization {
28 #define GEN_PASS_DEF_OPTIMIZEALLOCATIONLIVENESS
29 #include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
59 if (MemoryEffectOpInterface memEffectOp =
60 dyn_cast<MemoryEffectOpInterface>(user)) {
62 memEffectOp.getEffects(effects);
64 for (
const auto &effect : effects) {
65 if (isa<MemoryEffects::Free>(effect.getEffect())) {
67 LDBG(
"Multiple users with free effect found: " << *freeOpUser
80 static bool hasMemoryAllocEffect(MemoryEffectOpInterface memEffectOp) {
82 memEffectOp.getEffects(effects);
83 for (
const auto &effect : effects) {
84 if (isa<MemoryEffects::Allocate>(effect.getEffect())) {
91 struct OptimizeAllocationLiveness
92 :
public bufferization::impl::OptimizeAllocationLivenessBase<
93 OptimizeAllocationLiveness> {
95 OptimizeAllocationLiveness() =
default;
97 void runOnOperation()
override {
98 func::FuncOp func = getOperation();
100 if (func.isExternal())
105 func.walk([&](MemoryEffectOpInterface memEffectOp) ->
WalkResult {
106 if (!hasMemoryAllocEffect(memEffectOp))
109 auto allocOp = memEffectOp;
110 LDBG(
"Checking alloc op: " << allocOp);
112 auto deallocOp = findUserWithFreeSideEffect(allocOp->getResult(0));
113 if (!deallocOp || (deallocOp->getBlock() != allocOp->getBlock())) {
122 analysis.
resolve(allocOp->getResult(0));
123 for (
auto dep : llvm::make_early_inc_range(deps)) {
124 for (
auto user : dep.getUsers()) {
127 if (user == deallocOp)
131 auto topUser = allocOp->getBlock()->findAncestorOpInBlock(*user);
137 if (lastUser ==
nullptr) {
140 LDBG(
"Last user found: " << *lastUser);
141 assert(lastUser->
getBlock() == allocOp->getBlock());
142 assert(lastUser->
getBlock() == deallocOp->getBlock());
144 deallocOp->moveAfter(lastUser);
145 LDBG(
"Moved dealloc op after: " << *lastUser);
158 std::unique_ptr<Pass>
160 return std::make_unique<OptimizeAllocationLiveness>();
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...
ValueSetT resolve(Value value) const
Find all immediate and indirect views upon this value.
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 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()
std::unique_ptr< Pass > createOptimizeAllocationLivenessPass()
Creates a pass that finds all temporary allocations and attempts to move the deallocation after the l...
Include the generated interface declarations.