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.