diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2011-05-22 05:22:10 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2011-05-22 05:22:10 +0000 |
commit | 6d55f2269e20298a1d6a683be72d9552482156a9 (patch) | |
tree | 120cf5335e916d8079373f6d62d6b00cd71f2fbc /lib/Transforms/Utils/InlineFunction.cpp | |
parent | 9063b55f9b51850fa5f77abc699ab53ec639d9be (diff) |
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/Transforms/Utils/InlineFunction.cpp')
-rw-r--r-- | lib/Transforms/Utils/InlineFunction.cpp | 70 |
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) { |