22#include "llvm/Support/DebugLog.h"
24#define DEBUG_TYPE "optimize-allocation-liveness"
28#define GEN_PASS_DEF_OPTIMIZEALLOCATIONLIVENESSPASS
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
80static bool hasMemoryAllocEffect(MemoryEffectOpInterface memEffectOp) {
82 memEffectOp.getEffects(effects);
83 for (
const auto &effect : effects) {
84 if (isa<MemoryEffects::Allocate>(effect.getEffect())) {
93collectAllocations(MemoryEffectOpInterface allocOp) {
95 allocOp.getEffects(effects);
98 if (isa<MemoryEffects::Allocate>(it.getEffect()))
99 if (
auto val = it.getValue(); val && val.getDefiningOp() == allocOp)
100 allocResults.push_back(cast<OpResult>(val));
104struct OptimizeAllocationLiveness
106 OptimizeAllocationLiveness> {
108 OptimizeAllocationLiveness() =
default;
120 Operation *deallocOp,
121 Operation *lastUser) {
132 auto *definingOp = operand.getDefiningOp();
152 for (Operation *user :
result.getUsers()) {
159 return target->getNextNode();
162 void runOnOperation()
override {
163 func::FuncOp func = getOperation();
165 if (func.isExternal())
168 BufferViewFlowAnalysis
analysis = BufferViewFlowAnalysis(func);
169 auto domInfo = DominanceInfo();
171 func.walk([&](MemoryEffectOpInterface memEffectOp) -> WalkResult {
172 if (!hasMemoryAllocEffect(memEffectOp))
175 auto allocOp = memEffectOp;
176 LDBG() <<
"Checking alloc op: " << allocOp;
178 SmallVector<OpResult> allocationResults = collectAllocations(allocOp);
180 if (allocationResults.size() != 1)
183 OpResult allocResult = allocationResults[0];
184 LDBG() <<
"On allocation result: " << allocResult;
186 auto *deallocOp = findUserWithFreeSideEffect(allocResult);
194 Operation *lastUser =
nullptr;
197 for (
auto dep : llvm::make_early_inc_range(deps)) {
198 for (
auto *user : dep.getUsers()) {
201 if (user == deallocOp)
211 if (lastUser ==
nullptr) {
214 LDBG() <<
"Last user found: " << *lastUser;
221 LDBG() <<
"No valid insertion point found; skipping move";
226 LDBG() <<
"Moved dealloc op before: " << *
target;
static Operation * findValidInsertionPoint(Operation *emptyTensorOp, Operation *user, const SmallVector< Value > &neededValues)
Find a valid insertion point for a replacement of emptyTensorOp's use of user operation,...
Operation * findAncestorOpInBlock(Operation &op)
Returns 'op' if 'op' lies in this block, or otherwise finds the ancestor operation of 'op' that lies ...
SmallPtrSet< Value, 16 > ValueSetT
bool properlyDominates(Operation *a, Operation *b, bool enclosingOpOk=true) const
Return true if operation A properly dominates operation B, i.e.
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...
Block * getBlock()
Returns the operation block that contains this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
operand_range getOperands()
Returns an iterator on the underlying Value's.
void moveBefore(Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
result_range getResults()
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
static WalkResult advance()
SideEffects::EffectInstance< Effect > EffectInstance
Include the generated interface declarations.