@@ -2848,31 +2848,78 @@ struct LLVMOpAsmDialectInterface : public OpAsmDialectInterface {
28482848// DialectInlinerInterface
28492849// ===----------------------------------------------------------------------===//
28502850
2851+ // / Check whether the given alloca is an input to a lifetime intrinsic,
2852+ // / optionally passing through one or more casts on the way. This is not
2853+ // / transitive through block arguments.
2854+ static bool hasLifetimeMarkers (LLVM::AllocaOp allocaOp) {
2855+ SmallVector<Operation *> stack (allocaOp->getUsers ().begin (),
2856+ allocaOp->getUsers ().end ());
2857+ while (!stack.empty ()) {
2858+ Operation *op = stack.pop_back_val ();
2859+ if (isa<LLVM::LifetimeStartOp, LLVM::LifetimeEndOp>(op))
2860+ return true ;
2861+ if (isa<LLVM::BitcastOp>(op))
2862+ stack.append (op->getUsers ().begin (), op->getUsers ().end ());
2863+ }
2864+ return false ;
2865+ }
2866+
28512867// / Move all alloca operations with a constant size in the former entry block of
2852- // / the newly inlined callee into the entry block of the caller.
2868+ // / the newly inlined callee into the entry block of the caller, and insert
2869+ // / lifetime intrinsics that limit their scope to the inlined blocks.
28532870static void moveConstantAllocasToEntryBlock (
28542871 iterator_range<Region::iterator> inlinedBlocks) {
28552872 Block *calleeEntryBlock = &(*inlinedBlocks.begin ());
28562873 Block *callerEntryBlock = &(*calleeEntryBlock->getParent ()->begin ());
28572874 if (calleeEntryBlock == callerEntryBlock)
28582875 // Nothing to do.
28592876 return ;
2860- SmallVector<std::pair<LLVM::AllocaOp, IntegerAttr>> allocasToMove;
2877+ SmallVector<std::tuple<LLVM::AllocaOp, IntegerAttr, bool >> allocasToMove;
2878+ bool shouldInsertLifetimes = false ;
28612879 // Conservatively only move alloca operations that are part of the entry block
28622880 // and do not inspect nested regions, since they may execute conditionally or
28632881 // have other unknown semantics.
28642882 for (auto allocaOp : calleeEntryBlock->getOps <LLVM::AllocaOp>()) {
28652883 IntegerAttr arraySize;
2866- if (matchPattern (allocaOp.getArraySize (), m_Constant (&arraySize)))
2867- allocasToMove.emplace_back (allocaOp, arraySize);
2884+ if (!matchPattern (allocaOp.getArraySize (), m_Constant (&arraySize)))
2885+ continue ;
2886+ bool shouldInsertLifetime =
2887+ arraySize.getValue () != 0 && !hasLifetimeMarkers (allocaOp);
2888+ shouldInsertLifetimes |= shouldInsertLifetime;
2889+ allocasToMove.emplace_back (allocaOp, arraySize, shouldInsertLifetime);
28682890 }
2891+ if (allocasToMove.empty ())
2892+ return ;
28692893 OpBuilder builder (callerEntryBlock, callerEntryBlock->begin ());
2870- for (auto &[allocaOp, arraySize] : allocasToMove) {
2894+ for (auto &[allocaOp, arraySize, shouldInsertLifetime ] : allocasToMove) {
28712895 auto newConstant = builder.create <LLVM::ConstantOp>(
28722896 allocaOp->getLoc (), allocaOp.getArraySize ().getType (), arraySize);
2897+ // Insert a lifetime start intrinsic where the alloca was before moving it.
2898+ if (shouldInsertLifetime) {
2899+ OpBuilder::InsertionGuard insertionGuard (builder);
2900+ builder.setInsertionPoint (allocaOp);
2901+ builder.create <LLVM::LifetimeStartOp>(
2902+ allocaOp.getLoc (), arraySize.getValue ().getLimitedValue (),
2903+ allocaOp.getResult ());
2904+ }
28732905 allocaOp->moveAfter (newConstant);
28742906 allocaOp.getArraySizeMutable ().assign (newConstant.getResult ());
28752907 }
2908+ if (!shouldInsertLifetimes)
2909+ return ;
2910+ // Insert a lifetime end intrinsic before each return in the callee function.
2911+ for (Block &block : inlinedBlocks) {
2912+ if (!block.getTerminator ()->hasTrait <OpTrait::ReturnLike>())
2913+ continue ;
2914+ builder.setInsertionPoint (block.getTerminator ());
2915+ for (auto &[allocaOp, arraySize, shouldInsertLifetime] : allocasToMove) {
2916+ if (!shouldInsertLifetime)
2917+ continue ;
2918+ builder.create <LLVM::LifetimeEndOp>(
2919+ allocaOp.getLoc (), arraySize.getValue ().getLimitedValue (),
2920+ allocaOp.getResult ());
2921+ }
2922+ }
28762923}
28772924
28782925namespace {
@@ -2912,7 +2959,8 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
29122959 return false ;
29132960 return true ;
29142961 })
2915- .Case <LLVM::CallOp, LLVM::AllocaOp>([](auto ) { return true ; })
2962+ .Case <LLVM::CallOp, LLVM::AllocaOp, LLVM::LifetimeStartOp,
2963+ LLVM::LifetimeEndOp>([](auto ) { return true ; })
29162964 .Default ([](auto ) { return false ; });
29172965 }
29182966
0 commit comments