REALLY fix PR324: don't delete linkonce functions until after the SCC traversal
authorChris Lattner <sabre@nondot.org>
Tue, 20 Apr 2004 22:06:53 +0000 (22:06 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 20 Apr 2004 22:06:53 +0000 (22:06 +0000)
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

lib/Transforms/IPO/Inliner.cpp
lib/Transforms/IPO/Inliner.h

index 0684c28697e41645915aed1df9b832d70c4f4d6a..17e8001c5b579809f7792c6e8cc8f1ff2c0d6e4c 100644 (file)
@@ -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;
+}
index b63fe2ac05cebb74b816f404a500f6a6eeff38e9..45d5db726c01f5eccfc479ba800034fb8f11eaf0 100644 (file)
@@ -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.
   ///