From 096b8c0365e8e7f68105c04f274f02b15ce1f765 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Sat, 25 Feb 2012 02:56:01 +0000 Subject: [PATCH] Add support for disabling llvm.lifetime intrinsics in the AlwaysInliner. These are optimization hints, but at -O0 we're not optimizing. This becomes a problem when the alwaysinline attribute is abused. rdar://10921594 llvm-svn: 151429 --- include/llvm/Transforms/IPO.h | 1 + include/llvm/Transforms/IPO/InlinerPass.h | 5 ++++- include/llvm/Transforms/Utils/Cloning.h | 6 +++--- lib/Transforms/IPO/InlineAlways.cpp | 10 +++++++++- lib/Transforms/IPO/InlineSimple.cpp | 2 +- lib/Transforms/IPO/Inliner.cpp | 13 +++++++------ lib/Transforms/Utils/InlineFunction.cpp | 12 ++++++------ 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index f9d7f9e6b98..18176e8fdbb 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -94,6 +94,7 @@ Pass *createFunctionInliningPass(int Threshold); /// createAlwaysInlinerPass - Return a new pass object that inlines only /// functions that are marked as "always_inline". Pass *createAlwaysInlinerPass(); +Pass *createAlwaysInlinerPass(bool InsertLifetime); //===----------------------------------------------------------------------===// /// createPruneEHPass - Return a new pass object which transforms invoke diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h index 3ac4c591c94..1feaaa475b4 100644 --- a/include/llvm/Transforms/IPO/InlinerPass.h +++ b/include/llvm/Transforms/IPO/InlinerPass.h @@ -31,7 +31,7 @@ namespace llvm { /// struct Inliner : public CallGraphSCCPass { explicit Inliner(char &ID); - explicit Inliner(char &ID, int Threshold); + explicit Inliner(char &ID, int Threshold, bool InsertLifetime); /// getAnalysisUsage - For this class, we declare that we require and preserve /// the call graph. If the derived class implements this method, it should @@ -87,6 +87,9 @@ private: // InlineThreshold - Cache the value here for easy access. unsigned InlineThreshold; + // InsertLifetime - Insert @llvm.lifetime intrinsics. + bool InsertLifetime; + /// shouldInline - Return true if the inliner should attempt to /// inline at the given CallSite. bool shouldInline(CallSite CS); diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 16ff7cf1201..b7b5d29b320 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -197,9 +197,9 @@ public: /// exists in the instruction stream. Similarly this will inline a recursive /// function by one level. /// -bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI); -bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI); -bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI); +bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, bool InsertLifetime = true); +bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InsertLifetime = true); +bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime = true); } // End llvm namespace diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp index b9b78a1b552..b1fe24dcdbe 100644 --- a/lib/Transforms/IPO/InlineAlways.cpp +++ b/lib/Transforms/IPO/InlineAlways.cpp @@ -37,7 +37,11 @@ namespace { InlineCostAnalyzer CA; public: // Use extremely low threshold. - AlwaysInliner() : Inliner(ID, -2000000000) { + AlwaysInliner() : Inliner(ID, -2000000000, true) { + initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); + } + AlwaysInliner(bool InsertLifetime) : Inliner(ID, -2000000000, + InsertLifetime) { initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); } static char ID; // Pass identification, replacement for typeid @@ -72,6 +76,10 @@ INITIALIZE_PASS_END(AlwaysInliner, "always-inline", Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); } +Pass *llvm::createAlwaysInlinerPass(bool InsertLifetime) { + return new AlwaysInliner(InsertLifetime); +} + // doInitialization - Initializes the vector of functions that have not // been annotated with the "always inline" attribute. bool AlwaysInliner::doInitialization(CallGraph &CG) { diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 84dd4fdd988..c33d5ea0557 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -37,7 +37,7 @@ namespace { SimpleInliner() : Inliner(ID) { initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); } - SimpleInliner(int Threshold) : Inliner(ID, Threshold) { + SimpleInliner(int Threshold) : Inliner(ID, Threshold, true) { initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); } static char ID; // Pass identification, replacement for typeid diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index bdc9fe45d34..1f7625d3049 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -48,11 +48,12 @@ HintThreshold("inlinehint-threshold", cl::Hidden, cl::init(325), const int OptSizeThreshold = 75; Inliner::Inliner(char &ID) - : CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {} + : CallGraphSCCPass(ID), InlineThreshold(InlineLimit), InsertLifetime(true) {} -Inliner::Inliner(char &ID, int Threshold) +Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime) : CallGraphSCCPass(ID), InlineThreshold(InlineLimit.getNumOccurrences() > 0 ? - InlineLimit : Threshold) {} + InlineLimit : Threshold), + InsertLifetime(InsertLifetime) {} /// getAnalysisUsage - For this class, we declare that we require and preserve /// the call graph. If the derived class implements this method, it should @@ -75,13 +76,13 @@ InlinedArrayAllocasTy; /// any new allocas to the set if not possible. static bool InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI, InlinedArrayAllocasTy &InlinedArrayAllocas, - int InlineHistory) { + int InlineHistory, bool InsertLifetime) { Function *Callee = CS.getCalledFunction(); Function *Caller = CS.getCaller(); // Try to inline the function. Get the list of static allocas that were // inlined. - if (!InlineFunction(CS, IFI)) + if (!InlineFunction(CS, IFI, InsertLifetime)) return false; // If the inlined function had a higher stack protection level than the @@ -439,7 +440,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) { // Attempt to inline the function. if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas, - InlineHistoryID)) + InlineHistoryID, InsertLifetime)) continue; ++NumInlined; diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index fad56751b85..b84de054132 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -31,11 +31,11 @@ #include "llvm/Support/IRBuilder.h" using namespace llvm; -bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI) { - return InlineFunction(CallSite(CI), IFI); +bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI, bool InsertLifetime) { + return InlineFunction(CallSite(CI), IFI, InsertLifetime); } -bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI) { - return InlineFunction(CallSite(II), IFI); +bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InsertLifetime) { + return InlineFunction(CallSite(II), IFI, InsertLifetime); } namespace { @@ -484,7 +484,7 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, /// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now /// exists in the instruction stream. Similarly this will inline a recursive /// function by one level. -bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) { +bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime) { Instruction *TheCall = CS.getInstruction(); assert(TheCall->getParent() && TheCall->getParent()->getParent() && "Instruction not in function!"); @@ -655,7 +655,7 @@ 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()) { + if (InsertLifetime && !IFI.StaticAllocas.empty()) { IRBuilder<> builder(FirstNewBlock->begin()); for (unsigned ai = 0, ae = IFI.StaticAllocas.size(); ai != ae; ++ai) { AllocaInst *AI = IFI.StaticAllocas[ai];