diff options
author | Chris Lattner <sabre@nondot.org> | 2004-04-20 22:06:53 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-04-20 22:06:53 +0000 |
commit | 68d57e7ae80044401efd889270a12c71b3efb9ab (patch) | |
tree | a823a8a58a987be4c9952257451c9aa42e16e62d | |
parent | 72035995d50084676b2f9c1db0869f81f2faccf4 (diff) |
REALLY fix PR324: don't delete linkonce functions until after the SCC traversal
is done, which avoids invalidating iterators in the SCC traversal routines
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13088 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/IPO/Inliner.cpp | 35 | ||||
-rw-r--r-- | lib/Transforms/IPO/Inliner.h | 5 |
2 files changed, 33 insertions, 7 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 0684c28697..17e8001c5b 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -117,7 +117,7 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) { // If we inlined the last possible call site to the function, // delete the function body now. if (Callee->use_empty() && Callee != Caller && - (Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) { + Callee->hasInternalLinkage()) { DEBUG(std::cerr << " -> Deleting dead function: " << Callee->getName() << "\n"); SCCFunctions.erase(Callee); // Remove function from this SCC. @@ -126,12 +126,6 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) { while (CalleeNode->begin() != CalleeNode->end()) CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1)); - // If the function has external linkage (basically if it's a - // linkonce function) remove the edge from the external node to the - // callee node. - if (!Callee->hasInternalLinkage()) - CG.getExternalCallingNode()->removeCallEdgeTo(CalleeNode); - // Removing the node for callee from the call graph and delete it. delete CG.removeFunctionFromModule(CalleeNode); ++NumDeleted; @@ -145,3 +139,30 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) { return Changed; } +// doFinalization - Remove now-dead linkonce functions at the end of +// processing to avoid breaking the SCC traversal. +bool Inliner::doFinalization(CallGraph &CG) { + bool Changed = false; + for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ) { + CallGraphNode *CGN = (++I)->second; + Function *F = CGN ? CGN->getFunction() : 0; + if (F && (F->hasLinkOnceLinkage() || F->hasInternalLinkage()) && + F->use_empty()) { + // Remove any call graph edges from the callee to its callees. + while (CGN->begin() != CGN->end()) + CGN->removeCallEdgeTo(*(CGN->end()-1)); + + // If the function has external linkage (basically if it's a + // linkonce function) remove the edge from the external node to the + // callee node. + if (!F->hasInternalLinkage()) + CG.getExternalCallingNode()->removeCallEdgeTo(CGN); + + // Removing the node for callee from the call graph and delete it. + delete CG.removeFunctionFromModule(CGN); + ++NumDeleted; + Changed = true; + } + } + return Changed; +} diff --git a/lib/Transforms/IPO/Inliner.h b/lib/Transforms/IPO/Inliner.h index b63fe2ac05..45d5db726c 100644 --- a/lib/Transforms/IPO/Inliner.h +++ b/lib/Transforms/IPO/Inliner.h @@ -35,6 +35,11 @@ struct Inliner : public CallGraphSCCPass { // Pass class. virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC); + // doFinalization - Remove now-dead linkonce functions at the end of + // processing to avoid breaking the SCC traversal. + virtual bool doFinalization(CallGraph &CG); + + /// This method returns the value specified by the -inline-threshold value, /// specified on the command line. This is typically not directly needed. /// |