summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2011-05-22 05:22:10 +0000
committerNick Lewycky <nicholas@mxc.ca>2011-05-22 05:22:10 +0000
commit6d55f2269e20298a1d6a683be72d9552482156a9 (patch)
tree120cf5335e916d8079373f6d62d6b00cd71f2fbc /lib
parent9063b55f9b51850fa5f77abc699ab53ec639d9be (diff)
downloadllvm-6d55f2269e20298a1d6a683be72d9552482156a9.tar.gz
llvm-6d55f2269e20298a1d6a683be72d9552482156a9.tar.bz2
llvm-6d55f2269e20298a1d6a683be72d9552482156a9.tar.xz
Teach the inliner to emit llvm.lifetime.start/end, to scope the local variables
of the inlinee to the code representing the original function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131838 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 7d179092c0..bcdb72e23e 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -28,6 +28,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CallSite.h"
+#include "llvm/Support/IRBuilder.h"
using namespace llvm;
bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI) {
@@ -314,6 +315,41 @@ static Value *HandleByValArgument(Value *Arg, Instruction *TheCall,
return NewAlloca;
}
+// isUsedByLifetimeMarker - Check whether this Value is used by a lifetime
+// intrinsic.
+static bool isUsedByLifetimeMarker(Value *V) {
+ for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;
+ ++UI) {
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(*UI)) {
+ switch (II->getIntrinsicID()) {
+ default: break;
+ case Intrinsic::lifetime_start:
+ case Intrinsic::lifetime_end:
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// hasLifetimeMarkers - Check whether the given alloca already has
+// lifetime.start or lifetime.end intrinsics.
+static bool hasLifetimeMarkers(AllocaInst *AI) {
+ const Type *Int8PtrTy = Type::getInt8PtrTy(AI->getType()->getContext());
+ if (AI->getType() == Int8PtrTy)
+ return isUsedByLifetimeMarker(AI);
+
+ // Do a scan to find all the bitcasts to i8*.
+ for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); I != E;
+ ++I) {
+ if (I->getType() != Int8PtrTy) continue;
+ if (!isa<BitCastInst>(*I)) continue;
+ if (isUsedByLifetimeMarker(*I))
+ return true;
+ }
+ return false;
+}
+
// InlineFunction - This function inlines the called function into the basic
// block of the caller. This returns false if it is not possible to inline this
// call. The program is still in a well defined state if this occurs though.
@@ -460,6 +496,40 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) {
}
}
+ // Leave lifetime markers for the static alloca's, scoping them to the
+ // function we just inlined.
+ if (!IFI.StaticAllocas.empty()) {
+ // Also preserve the call graph, if applicable.
+ CallGraphNode *StartCGN = 0, *EndCGN = 0, *CallerNode = 0;
+ if (CallGraph *CG = IFI.CG) {
+ Function *Start = Intrinsic::getDeclaration(Caller->getParent(),
+ Intrinsic::lifetime_start);
+ Function *End = Intrinsic::getDeclaration(Caller->getParent(),
+ Intrinsic::lifetime_end);
+ StartCGN = CG->getOrInsertFunction(Start);
+ EndCGN = CG->getOrInsertFunction(End);
+ CallerNode = (*CG)[Caller];
+ }
+
+ IRBuilder<> builder(FirstNewBlock->begin());
+ for (unsigned ai = 0, ae = IFI.StaticAllocas.size(); ai != ae; ++ai) {
+ AllocaInst *AI = IFI.StaticAllocas[ai];
+
+ // If the alloca is already scoped to something smaller than the whole
+ // function then there's no need to add redundant, less accurate markers.
+ if (hasLifetimeMarkers(AI))
+ continue;
+
+ CallInst *StartCall = builder.CreateLifetimeStart(AI);
+ if (IFI.CG) CallerNode->addCalledFunction(StartCall, StartCGN);
+ for (unsigned ri = 0, re = Returns.size(); ri != re; ++ri) {
+ IRBuilder<> builder(Returns[ri]);
+ CallInst *EndCall = builder.CreateLifetimeEnd(AI);
+ if (IFI.CG) CallerNode->addCalledFunction(EndCall, EndCGN);
+ }
+ }
+ }
+
// If the inlined code contained dynamic alloca instructions, wrap the inlined
// code with llvm.stacksave/llvm.stackrestore intrinsics.
if (InlinedFunctionInfo.ContainsDynamicAllocas) {