Teach internalize to preserve the callgraph.
authorDuncan Sands <baldrick@free.fr>
Fri, 3 Oct 2008 07:36:09 +0000 (07:36 +0000)
committerDuncan Sands <baldrick@free.fr>
Fri, 3 Oct 2008 07:36:09 +0000 (07:36 +0000)
Why?  Because it was there!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56996 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/CallGraph.h
lib/Analysis/IPA/CallGraph.cpp
lib/Transforms/IPO/Internalize.cpp

index e63db750ea3f9d66d6e9833a3643ef630317d0b5..27a6ab357fdfaaea0eb99f4937015e6b40a00d45 100644 (file)
@@ -225,11 +225,15 @@ public:
   /// should be used sparingly.
   void removeCallEdgeFor(CallSite CS);
 
-  /// removeAnyCallEdgeTo - This method removes any call edges from this node to
-  /// the specified callee function.  This takes more time to execute than
+  /// removeAnyCallEdgeTo - This method removes all call edges from this node
+  /// to the specified callee function.  This takes more time to execute than
   /// removeCallEdgeTo, so it should not be used unless necessary.
   void removeAnyCallEdgeTo(CallGraphNode *Callee);
 
+  /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
+  /// from this node to the specified callee function.
+  void removeOneAbstractEdgeTo(CallGraphNode *Callee);
+
   /// replaceCallSite - Make the edge in the node for Old CallSite be for
   /// New CallSite instead.  Note that this method takes linear time, so it
   /// should be used sparingly.
index fba1d00d48c067b29fb6371b42115ed0ee65dfab..5aac2968b2275414289adbee9b69d55c5ff4b781 100644 (file)
@@ -282,6 +282,19 @@ void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {
     }
 }
 
+/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
+/// from this node to the specified callee function.
+void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) {
+  for (unsigned i = CalledFunctions.size(); ; --i) {
+    assert(i && "Cannot find callee to remove!");
+    CallRecord &CR = CalledFunctions[i-1];
+    if (CR.second == Callee && !CR.first.getInstruction()) {
+      CalledFunctions.erase(CalledFunctions.begin()+i-1);
+      return;
+    }
+  }
+}
+
 /// replaceCallSite - Make the edge in the node for Old CallSite be for
 /// New CallSite instead.  Note that this method takes linear time, so it
 /// should be used sparingly.
index 47fe5fe85ad3b31969119e76273a4b03effe046d..462daab02642f8f7ba232ade280c6e81d2e79884 100644 (file)
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "internalize"
+#include "llvm/Analysis/CallGraph.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Pass.h"
 #include "llvm/Module.h"
@@ -55,6 +56,7 @@ namespace {
 
     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesCFG();
+      AU.addPreserved<CallGraph>();
     }
   };
 } // end anonymous namespace
@@ -96,6 +98,9 @@ void InternalizePass::LoadFile(const char *Filename) {
 }
 
 bool InternalizePass::runOnModule(Module &M) {
+  CallGraph *CG = getAnalysisToUpdate<CallGraph>();
+  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
+
   if (ExternalNames.empty()) {
     // Return if we're not in 'all but main' mode and have no external api
     if (!AllButMain)
@@ -120,6 +125,8 @@ bool InternalizePass::runOnModule(Module &M) {
         !I->hasInternalLinkage() &&  // Can't already have internal linkage
         !ExternalNames.count(I->getName())) {// Not marked to keep external?
       I->setLinkage(GlobalValue::InternalLinkage);
+      // Remove a callgraph edge from the external node to this function.
+      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
       Changed = true;
       ++NumFunctions;
       DOUT << "Internalizing func " << I->getName() << "\n";