summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/CodeExtractor.cpp
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2019-02-13 19:53:38 +0000
committerVedant Kumar <vsk@apple.com>2019-02-13 19:53:38 +0000
commit4b0cc9a7c80ff44ff63f87305c775186a6360497 (patch)
tree16a8edb450be27bc3036fe795ec2f744ebe5aa9d /llvm/lib/Transforms/Utils/CodeExtractor.cpp
parent9fc51bae7342301bc2fbd93d254bbd53ec86256e (diff)
downloadbcm5719-llvm-4b0cc9a7c80ff44ff63f87305c775186a6360497.tar.gz
bcm5719-llvm-4b0cc9a7c80ff44ff63f87305c775186a6360497.zip
[CodeExtractor] Only lift lifetime markers present in the extraction region
When CodeExtractor finds liftime markers referencing inputs to the extraction region, it lifts these markers out of the region and inserts them around the call to the extracted function (see r350420, PR39671). However, it should *only* lift lifetime markers that are actually present in the extraction region. I.e., if a start marker is present in the extraction region but a corresponding end marker isn't (or vice versa), only the start marker (or end marker, resp.) should be lifted. Differential Revision: https://reviews.llvm.org/D57834 llvm-svn: 353973
Diffstat (limited to 'llvm/lib/Transforms/Utils/CodeExtractor.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/CodeExtractor.cpp96
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())
OpenPOWER on IntegriCloud