diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Utils/CodeExtractor.cpp | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 393a7461c54..2e073e89dde 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -885,16 +885,17 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, return newFunction; } -/// Scan the extraction region for lifetime markers which reference inputs. -/// Erase these markers. Return the inputs which were referenced. +/// Erase lifetime.start markers which reference inputs to the extraction +/// region, and insert the referenced memory into \p LifetimesStart. Do the same +/// with lifetime.end markers (but insert them into \p LifetimesEnd). /// /// The extraction region is defined by a set of blocks (\p Blocks), and a set /// of allocas which will be moved from the caller function into the extracted /// function (\p SunkAllocas). -static SetVector<Value *> -eraseLifetimeMarkersOnInputs(const SetVector<BasicBlock *> &Blocks, - const SetVector<Value *> &SunkAllocas) { - SetVector<Value *> InputObjectsWithLifetime; +static void eraseLifetimeMarkersOnInputs(const SetVector<BasicBlock *> &Blocks, + const SetVector<Value *> &SunkAllocas, + SetVector<Value *> &LifetimesStart, + SetVector<Value *> &LifetimesEnd) { for (BasicBlock *BB : Blocks) { for (auto It = BB->begin(), End = BB->end(); It != End;) { auto *II = dyn_cast<IntrinsicInst>(&*It); @@ -909,44 +910,64 @@ eraseLifetimeMarkersOnInputs(const SetVector<BasicBlock *> &Blocks, if (SunkAllocas.count(Mem) || definedInRegion(Blocks, Mem)) continue; - InputObjectsWithLifetime.insert(Mem); + if (II->getIntrinsicID() == Intrinsic::lifetime_start) + LifetimesStart.insert(Mem); + else + LifetimesEnd.insert(Mem); II->eraseFromParent(); } } - return InputObjectsWithLifetime; } /// Insert lifetime start/end markers surrounding the call to the new function /// for objects defined in the caller. -static void insertLifetimeMarkersSurroundingCall(Module *M, - ArrayRef<Value *> Objects, - CallInst *TheCall) { - if (Objects.empty()) - return; - +static void insertLifetimeMarkersSurroundingCall( + Module *M, ArrayRef<Value *> LifetimesStart, ArrayRef<Value *> LifetimesEnd, + CallInst *TheCall) { LLVMContext &Ctx = M->getContext(); auto Int8PtrTy = Type::getInt8PtrTy(Ctx); auto NegativeOne = ConstantInt::getSigned(Type::getInt64Ty(Ctx), -1); - auto StartFn = llvm::Intrinsic::getDeclaration( - M, llvm::Intrinsic::lifetime_start, Int8PtrTy); - auto EndFn = llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::lifetime_end, - Int8PtrTy); Instruction *Term = TheCall->getParent()->getTerminator(); - for (Value *Mem : Objects) { - assert((!isa<Instruction>(Mem) || - cast<Instruction>(Mem)->getFunction() == TheCall->getFunction()) && - "Input memory not defined in original function"); - Value *MemAsI8Ptr = nullptr; - if (Mem->getType() == Int8PtrTy) - MemAsI8Ptr = Mem; - else - MemAsI8Ptr = - CastInst::CreatePointerCast(Mem, Int8PtrTy, "lt.cast", TheCall); - auto StartMarker = CallInst::Create(StartFn, {NegativeOne, MemAsI8Ptr}); - StartMarker->insertBefore(TheCall); - auto EndMarker = CallInst::Create(EndFn, {NegativeOne, MemAsI8Ptr}); - EndMarker->insertBefore(Term); + // The memory argument to a lifetime marker must be a i8*. Cache any bitcasts + // needed to satisfy this requirement so they may be reused. + DenseMap<Value *, Value *> Bitcasts; + + // Emit lifetime markers for the pointers given in \p Objects. Insert the + // markers before the call if \p InsertBefore, and after the call otherwise. + auto insertMarkers = [&](Function *MarkerFunc, ArrayRef<Value *> Objects, + bool InsertBefore) { + for (Value *Mem : Objects) { + assert((!isa<Instruction>(Mem) || cast<Instruction>(Mem)->getFunction() == + TheCall->getFunction()) && + "Input memory not defined in original function"); + Value *&MemAsI8Ptr = Bitcasts[Mem]; + if (!MemAsI8Ptr) { + if (Mem->getType() == Int8PtrTy) + MemAsI8Ptr = Mem; + else + MemAsI8Ptr = + CastInst::CreatePointerCast(Mem, Int8PtrTy, "lt.cast", TheCall); + } + + auto Marker = CallInst::Create(MarkerFunc, {NegativeOne, MemAsI8Ptr}); + if (InsertBefore) + Marker->insertBefore(TheCall); + else + Marker->insertBefore(Term); + } + }; + + if (!LifetimesStart.empty()) { + auto StartFn = llvm::Intrinsic::getDeclaration( + M, llvm::Intrinsic::lifetime_start, Int8PtrTy); + insertMarkers(StartFn, LifetimesStart, /*InsertBefore=*/true); + } + + if (!LifetimesEnd.empty()) { + auto EndFn = llvm::Intrinsic::getDeclaration( + M, llvm::Intrinsic::lifetime_end, Int8PtrTy); + insertMarkers(EndFn, LifetimesEnd, /*InsertBefore=*/false); } } @@ -1214,7 +1235,7 @@ CallInst *CodeExtractor::emitCallAndSwitchStatement(Function *newFunction, // Insert lifetime markers around the reloads of any output values. The // allocas output values are stored in are only in-use in the codeRepl block. - insertLifetimeMarkersSurroundingCall(M, ReloadOutputs, call); + insertLifetimeMarkersSurroundingCall(M, ReloadOutputs, ReloadOutputs, call); return call; } @@ -1403,8 +1424,9 @@ Function *CodeExtractor::extractCodeRegion() { // referenced by lifetime start/end markers within it. The effects of these // markers must be replicated in the calling function to prevent the stack // coloring pass from merging slots which store input objects. - ValueSet InputObjectsWithLifetime = - eraseLifetimeMarkersOnInputs(Blocks, SinkingCands); + ValueSet LifetimesStart, LifetimesEnd; + eraseLifetimeMarkersOnInputs(Blocks, SinkingCands, LifetimesStart, + LifetimesEnd); // Construct new function based on inputs/outputs & add allocas for all defs. Function *newFunction = @@ -1428,8 +1450,8 @@ Function *CodeExtractor::extractCodeRegion() { // Replicate the effects of any lifetime start/end markers which referenced // input objects in the extraction region by placing markers around the call. insertLifetimeMarkersSurroundingCall(oldFunction->getParent(), - InputObjectsWithLifetime.getArrayRef(), - TheCall); + LifetimesStart.getArrayRef(), + LifetimesEnd.getArrayRef(), TheCall); // Propagate personality info to the new function if there is one. if (oldFunction->hasPersonalityFn()) |