diff options
Diffstat (limited to 'lib/Transforms/IPO/PruneEH.cpp')
-rw-r--r-- | lib/Transforms/IPO/PruneEH.cpp | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp index 22a95fa03f7c5..2aa3fa55cefdc 100644 --- a/lib/Transforms/IPO/PruneEH.cpp +++ b/lib/Transforms/IPO/PruneEH.cpp @@ -16,7 +16,6 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/CallGraph.h" @@ -48,10 +47,10 @@ namespace { // runOnSCC - Analyze the SCC, performing the transformation if possible. bool runOnSCC(CallGraphSCC &SCC) override; - bool SimplifyFunction(Function *F); - void DeleteBasicBlock(BasicBlock *BB); }; } +static bool SimplifyFunction(Function *F, CallGraph &CG); +static void DeleteBasicBlock(BasicBlock *BB, CallGraph &CG); char PruneEH::ID = 0; INITIALIZE_PASS_BEGIN(PruneEH, "prune-eh", @@ -62,22 +61,20 @@ INITIALIZE_PASS_END(PruneEH, "prune-eh", Pass *llvm::createPruneEHPass() { return new PruneEH(); } - -bool PruneEH::runOnSCC(CallGraphSCC &SCC) { +static bool runImpl(CallGraphSCC &SCC, CallGraph &CG) { SmallPtrSet<CallGraphNode *, 8> SCCNodes; - CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); bool MadeChange = false; // Fill SCCNodes with the elements of the SCC. Used for quickly // looking up whether a given CallGraphNode is in this SCC. - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) - SCCNodes.insert(*I); + for (CallGraphNode *I : SCC) + SCCNodes.insert(I); // First pass, scan all of the functions in the SCC, simplifying them // according to what we know. - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) - if (Function *F = (*I)->getFunction()) - MadeChange |= SimplifyFunction(F); + for (CallGraphNode *I : SCC) + if (Function *F = I->getFunction()) + MadeChange |= SimplifyFunction(F, CG); // Next, check to see if any callees might throw or if there are any external // functions in this SCC: if so, we cannot prune any functions in this SCC. @@ -93,7 +90,10 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) { if (!F) { SCCMightUnwind = true; SCCMightReturn = true; - } else if (F->isDeclaration() || F->mayBeOverridden()) { + } else if (F->isDeclaration() || F->isInterposable()) { + // Note: isInterposable (as opposed to hasExactDefinition) is fine above, + // since we're not inferring new attributes here, but only using existing, + // assumed to be correct, function attributes. SCCMightUnwind |= !F->doesNotThrow(); SCCMightReturn |= !F->doesNotReturn(); } else { @@ -153,8 +153,8 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) { // If the SCC doesn't unwind or doesn't throw, note this fact. if (!SCCMightUnwind || !SCCMightReturn) - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { - Function *F = (*I)->getFunction(); + for (CallGraphNode *I : SCC) { + Function *F = I->getFunction(); if (!SCCMightUnwind && !F->hasFnAttribute(Attribute::NoUnwind)) { F->addFnAttr(Attribute::NoUnwind); @@ -167,22 +167,30 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) { } } - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { + for (CallGraphNode *I : SCC) { // Convert any invoke instructions to non-throwing functions in this node // into call instructions with a branch. This makes the exception blocks // dead. - if (Function *F = (*I)->getFunction()) - MadeChange |= SimplifyFunction(F); + if (Function *F = I->getFunction()) + MadeChange |= SimplifyFunction(F, CG); } return MadeChange; } +bool PruneEH::runOnSCC(CallGraphSCC &SCC) { + if (skipSCC(SCC)) + return false; + CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); + return runImpl(SCC, CG); +} + + // SimplifyFunction - Given information about callees, simplify the specified // function if we have invokes to non-unwinding functions or code after calls to // no-return functions. -bool PruneEH::SimplifyFunction(Function *F) { +static bool SimplifyFunction(Function *F, CallGraph &CG) { bool MadeChange = false; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) @@ -192,7 +200,7 @@ bool PruneEH::SimplifyFunction(Function *F) { // If the unwind block is now dead, nuke it. if (pred_empty(UnwindBlock)) - DeleteBasicBlock(UnwindBlock); // Delete the new BB. + DeleteBasicBlock(UnwindBlock, CG); // Delete the new BB. ++NumRemoved; MadeChange = true; @@ -211,7 +219,7 @@ bool PruneEH::SimplifyFunction(Function *F) { BB->getInstList().pop_back(); new UnreachableInst(BB->getContext(), &*BB); - DeleteBasicBlock(New); // Delete the new BB. + DeleteBasicBlock(New, CG); // Delete the new BB. MadeChange = true; ++NumUnreach; break; @@ -224,9 +232,8 @@ bool PruneEH::SimplifyFunction(Function *F) { /// DeleteBasicBlock - remove the specified basic block from the program, /// updating the callgraph to reflect any now-obsolete edges due to calls that /// exist in the BB. -void PruneEH::DeleteBasicBlock(BasicBlock *BB) { +static void DeleteBasicBlock(BasicBlock *BB, CallGraph &CG) { assert(pred_empty(BB) && "BB is not dead!"); - CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); Instruction *TokenInst = nullptr; |