summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/Inliner.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-04-20 22:06:53 +0000
committerChris Lattner <sabre@nondot.org>2004-04-20 22:06:53 +0000
commit68d57e7ae80044401efd889270a12c71b3efb9ab (patch)
treea823a8a58a987be4c9952257451c9aa42e16e62d /lib/Transforms/IPO/Inliner.cpp
parent72035995d50084676b2f9c1db0869f81f2faccf4 (diff)
downloadllvm-68d57e7ae80044401efd889270a12c71b3efb9ab.tar.gz
llvm-68d57e7ae80044401efd889270a12c71b3efb9ab.tar.bz2
llvm-68d57e7ae80044401efd889270a12c71b3efb9ab.tar.xz
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
Diffstat (limited to 'lib/Transforms/IPO/Inliner.cpp')
-rw-r--r--lib/Transforms/IPO/Inliner.cpp35
1 files changed, 28 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;
+}