Change the callgraph representation to store the callsite along with the
authorChris Lattner <sabre@nondot.org>
Wed, 12 Jul 2006 18:29:36 +0000 (18:29 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 12 Jul 2006 18:29:36 +0000 (18:29 +0000)
target CG node.  This allows the inliner to properly update the callgraph
when using the pruning inliner.  The pruning inliner may not copy over all
call sites from a callee to a caller, so the edges corresponding to those
call sites should not be copied over either.

This fixes PR827 and Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll

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

include/llvm/Analysis/CallGraph.h
lib/Analysis/IPA/CallGraph.cpp
lib/Analysis/IPA/GlobalsModRef.cpp
lib/Transforms/IPO/Inliner.cpp
lib/Transforms/Utils/InlineFunction.cpp

index 94cea100485b622dec65602386754a9c38efd51c..b567bab474f158b2b21991efe482bf5425d08e87 100644 (file)
@@ -54,6 +54,7 @@
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Pass.h"
+#include "llvm/Support/CallSite.h"
 
 namespace llvm {
 
@@ -167,7 +168,8 @@ protected:
 //
 class CallGraphNode {
   Function *F;
-  std::vector<CallGraphNode*> CalledFunctions;
+  typedef std::pair<CallSite,CallGraphNode*> CallRecord;
+  std::vector<CallRecord> CalledFunctions;
 
   CallGraphNode(const CallGraphNode &);           // Do not implement
 public:
@@ -175,8 +177,8 @@ public:
   // Accessor methods...
   //
 
-  typedef std::vector<CallGraphNode*>::iterator iterator;
-  typedef std::vector<CallGraphNode*>::const_iterator const_iterator;
+  typedef std::vector<CallRecord>::iterator iterator;
+  typedef std::vector<CallRecord>::const_iterator const_iterator;
 
   // getFunction - Return the function that this call graph node represents...
   Function *getFunction() const { return F; }
@@ -189,7 +191,9 @@ public:
 
   // Subscripting operator - Return the i'th called function...
   //
-  CallGraphNode *operator[](unsigned i) const { return CalledFunctions[i];}
+  CallGraphNode *operator[](unsigned i) const {
+    return CalledFunctions[i].second;
+  }
 
   /// dump - Print out this call graph node.
   ///
@@ -209,8 +213,8 @@ public:
 
   /// addCalledFunction add a function to the list of functions called by this
   /// one.
-  void addCalledFunction(CallGraphNode *M) {
-    CalledFunctions.push_back(M);
+  void addCalledFunction(CallSite CS, CallGraphNode *M) {
+    CalledFunctions.push_back(std::make_pair(CS, M));
   }
 
   /// removeCallEdgeTo - This method removes a *single* edge to the specified
@@ -225,24 +229,38 @@ public:
 
   friend class CallGraph;
 
-  // CallGraphNode ctor - Create a node for the specified function...
+  // CallGraphNode ctor - Create a node for the specified function.
   inline CallGraphNode(Function *f) : F(f) {}
 };
 
 //===----------------------------------------------------------------------===//
 // GraphTraits specializations for call graphs so that they can be treated as
-// graphs by the generic graph algorithms...
+// graphs by the generic graph algorithms.
 //
 
 // Provide graph traits for tranversing call graphs using standard graph
 // traversals.
 template <> struct GraphTraits<CallGraphNode*> {
   typedef CallGraphNode NodeType;
-  typedef NodeType::iterator ChildIteratorType;
 
+  typedef std::pair<CallSite, CallGraphNode*> CGNPairTy;
+  typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun;
+  
   static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; }
-  static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
-  static inline ChildIteratorType child_end  (NodeType *N) { return N->end(); }
+  
+  typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
+  
+  static inline ChildIteratorType child_begin(NodeType *N) {
+    return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
+  }
+  static inline ChildIteratorType child_end  (NodeType *N) {
+    return map_iterator(N->end(), CGNDerefFun(CGNDeref));
+  }
+  
+  static CallGraphNode *CGNDeref(CGNPairTy P) {
+    return P.second;
+  }
+  
 };
 
 template <> struct GraphTraits<const CallGraphNode*> {
@@ -270,8 +288,7 @@ template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {
     return map_iterator(CG->end(), DerefFun(CGdereference));
   }
 
-  static CallGraphNode &CGdereference (std::pair<const Function*,
-                                       CallGraphNode*> P) {
+  static CallGraphNode &CGdereference(PairTy P) {
     return *P.second;
   }
 };
index 78bb735ffa23aa84610125ac260ad575fa32803d..23a7599ce57138da2d9199fe3d32a7ff5a9770d4 100644 (file)
@@ -112,9 +112,9 @@ private:
   void addToCallGraph(Function *F) {
     CallGraphNode *Node = getOrInsertFunction(F);
 
-    // If this function has external linkage, anything could call it...
+    // If this function has external linkage, anything could call it.
     if (!F->hasInternalLinkage()) {
-      ExternalCallingNode->addCalledFunction(Node);
+      ExternalCallingNode->addCalledFunction(CallSite(), Node);
 
       // Found the entry point?
       if (F->getName() == "main") {
@@ -128,27 +128,29 @@ private:
     // If this function is not defined in this translation unit, it could call
     // anything.
     if (F->isExternal() && !F->getIntrinsicID())
-      Node->addCalledFunction(CallsExternalNode);
+      Node->addCalledFunction(CallSite(), CallsExternalNode);
 
     // Loop over all of the users of the function... looking for callers...
     //
     bool isUsedExternally = false;
     for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I){
       if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
-        if (isOnlyADirectCall(F, CallSite::get(Inst)))
+        CallSite CS = CallSite::get(Inst);
+        if (isOnlyADirectCall(F, CS))
           getOrInsertFunction(Inst->getParent()->getParent())
-              ->addCalledFunction(Node);
+              ->addCalledFunction(CS, Node);
         else
           isUsedExternally = true;
       } else if (GlobalValue *GV = dyn_cast<GlobalValue>(*I)) {
         for (Value::use_iterator I = GV->use_begin(), E = GV->use_end();
              I != E; ++I)
           if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
-          if (isOnlyADirectCall(F, CallSite::get(Inst)))
-            getOrInsertFunction(Inst->getParent()->getParent())
-                ->addCalledFunction(Node);
-          else
-            isUsedExternally = true;
+            CallSite CS = CallSite::get(Inst);
+            if (isOnlyADirectCall(F, CS))
+              getOrInsertFunction(Inst->getParent()->getParent())
+                ->addCalledFunction(CS, Node);
+            else
+              isUsedExternally = true;
           } else {
             isUsedExternally = true;
           }
@@ -157,15 +159,15 @@ private:
       }
     }
     if (isUsedExternally)
-      ExternalCallingNode->addCalledFunction(Node);
+      ExternalCallingNode->addCalledFunction(CallSite(), Node);
 
-  // Look for an indirect function call...
+    // Look for an indirect function call.
     for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
       for (BasicBlock::iterator II = BB->begin(), IE = BB->end();
            II != IE; ++II) {
       CallSite CS = CallSite::get(II);
       if (CS.getInstruction() && !CS.getCalledFunction())
-        Node->addCalledFunction(CallsExternalNode);
+        Node->addCalledFunction(CS, CallsExternalNode);
       }
   }
 
@@ -261,8 +263,8 @@ void CallGraphNode::print(std::ostream &OS) const {
     OS << "Call graph node <<null function: 0x" << this << ">>:\n";
 
   for (const_iterator I = begin(), E = end(); I != E; ++I)
-    if ((*I)->getFunction())
-      OS << "  Calls function '" << (*I)->getFunction()->getName() << "'\n";
+    if (I->second->getFunction())
+      OS << "  Calls function '" << I->second->getFunction()->getName() <<"'\n";
   else
     OS << "  Calls external node\n";
   OS << "\n";
@@ -273,7 +275,7 @@ void CallGraphNode::dump() const { print(std::cerr); }
 void CallGraphNode::removeCallEdgeTo(CallGraphNode *Callee) {
   for (unsigned i = CalledFunctions.size(); ; --i) {
     assert(i && "Cannot find callee to remove!");
-    if (CalledFunctions[i-1] == Callee) {
+    if (CalledFunctions[i-1].second == Callee) {
       CalledFunctions.erase(CalledFunctions.begin()+i-1);
       return;
     }
@@ -285,7 +287,7 @@ void CallGraphNode::removeCallEdgeTo(CallGraphNode *Callee) {
 // removeCallEdgeTo, so it should not be used unless necessary.
 void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {
   for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i)
-    if (CalledFunctions[i] == Callee) {
+    if (CalledFunctions[i].second == Callee) {
       CalledFunctions[i] = CalledFunctions.back();
       CalledFunctions.pop_back();
       --i; --e;
index 5b3c953bcdfa25925dc078aa94a5bcd11fd1bc83..4765b096b38777bf5e07d1e6817168b61f877cda 100644 (file)
@@ -263,7 +263,7 @@ void GlobalsModRef::AnalyzeSCC(std::vector<CallGraphNode *> &SCC) {
   for (unsigned i = 0, e = SCC.size(); i != e && !CallsExternal; ++i)
     for (CallGraphNode::iterator CI = SCC[i]->begin(), E = SCC[i]->end();
          CI != E; ++CI)
-      if (Function *Callee = (*CI)->getFunction()) {
+      if (Function *Callee = CI->second->getFunction()) {
         if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) {
           // Propagate function effect up.
           FunctionEffect |= CalleeFR->FunctionEffect;
index 89999bb4425c274c201c750bea9ad16f841c5306..ae4032bbfb30b0fa405cfacf061f98cb9eb9eebb 100644 (file)
@@ -54,7 +54,7 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
     // Remove any call graph edges from the callee to its callees.
     CallGraphNode *CalleeNode = CG[Callee];
     while (CalleeNode->begin() != CalleeNode->end())
-      CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1));
+      CalleeNode->removeCallEdgeTo((CalleeNode->end()-1)->second);
 
     // Removing the node for callee from the call graph and delete it.
     delete CG.removeFunctionFromModule(CalleeNode);
@@ -168,7 +168,7 @@ bool Inliner::doFinalization(CallGraph &CG) {
 
         // Remove any call graph edges from the function to its callees.
         while (CGN->begin() != CGN->end())
-          CGN->removeCallEdgeTo(*(CGN->end()-1));
+          CGN->removeCallEdgeTo((CGN->end()-1)->second);
 
         // Remove any edges from the external node to the function's call graph
         // node.  These edges might have been made irrelegant due to
index 37ba3ba6d49f40ab814979b572c0c94bc226ae60..277b10a767f88e828d8b53a991712043944a492a 100644 (file)
@@ -136,22 +136,32 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
   InvokeDest->removePredecessor(II->getParent());
 }
 
-/// UpdateCallGraphAfterInlining - Once we have finished inlining a call from
-/// caller to callee, update the specified callgraph to reflect the changes we
-/// made.
-static void UpdateCallGraphAfterInlining(const Function *Caller, 
+/// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee
+/// into the caller, update the specified callgraph to reflect the changes we
+/// made.  Note that it's possible that not all code was copied over, so only
+/// some edges of the callgraph will be remain.
+static void UpdateCallGraphAfterInlining(const Function *Caller,
                                          const Function *Callee,
+                                         Function::iterator FirstNewBlock,
+                                       std::map<const Value*, Value*> &ValueMap,
                                          CallGraph &CG) {
   // Update the call graph by deleting the edge from Callee to Caller
   CallGraphNode *CalleeNode = CG[Callee];
   CallGraphNode *CallerNode = CG[Caller];
   CallerNode->removeCallEdgeTo(CalleeNode);
   
-  // Since we inlined all uninlined call sites in the callee into the caller,
+  // Since we inlined some uninlined call sites in the callee into the caller,
   // add edges from the caller to all of the callees of the callee.
   for (CallGraphNode::iterator I = CalleeNode->begin(),
-       E = CalleeNode->end(); I != E; ++I)
-    CallerNode->addCalledFunction(*I);
+       E = CalleeNode->end(); I != E; ++I) {
+    const Instruction *OrigCall = I->first.getInstruction();
+    
+    std::map<const Value*, Value*>::iterator VMI = ValueMap.find(OrigCall);
+    if (VMI != ValueMap.end()) { // Only copy the edge if the call was inlined!
+      Instruction *NewCall = cast<Instruction>(VMI->second);
+      CallerNode->addCalledFunction(CallSite::get(NewCall), I->second);
+    }
+  }
 }
 
 
@@ -192,6 +202,8 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
   // function.
   std::vector<ReturnInst*> Returns;
   ClonedCodeInfo InlinedFunctionInfo;
+  Function::iterator FirstNewBlock;
+  
   { // Scope to destroy ValueMap after cloning.
     std::map<const Value*, Value*> ValueMap;
 
@@ -211,11 +223,16 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
     // happy with whatever the cloner can do.
     CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i",
                               &InlinedFunctionInfo);
+    
+    // Remember the first block that is newly cloned over.
+    FirstNewBlock = LastBlock; ++FirstNewBlock;
+    
+    // Update the callgraph if requested.
+    if (CG)
+      UpdateCallGraphAfterInlining(Caller, CalledFunc, FirstNewBlock, ValueMap,
+                                   *CG);
   }
-
-  // Remember the first block that is newly cloned over.
-  Function::iterator FirstNewBlock = LastBlock; ++FirstNewBlock;
-
   // If there are any alloca instructions in the block that used to be the entry
   // block for the callee, move them to the entry block of the caller.  First
   // calculate which instruction they should be inserted before.  We insert the
@@ -252,15 +269,27 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
     StackSave    = M->getOrInsertFunction("llvm.stacksave", SBytePtr, NULL);
     StackRestore = M->getOrInsertFunction("llvm.stackrestore", Type::VoidTy,
                                           SBytePtr, NULL);
-    
+
+    // If we are preserving the callgraph, add edges to the stacksave/restore
+    // functions for the calls we insert.
+    CallGraphNode *StackSaveCGN, *StackRestoreCGN, *CallerNode;
+    if (CG) {
+      StackSaveCGN    = CG->getOrInsertFunction(StackSave);
+      StackRestoreCGN = CG->getOrInsertFunction(StackRestore);
+      CallerNode = (*CG)[Caller];
+    }
+      
     // Insert the llvm.stacksave.
-    Value *SavedPtr = new CallInst(StackSave, "savedstack", 
-                                   FirstNewBlock->begin());
-    
+    CallInst *SavedPtr = new CallInst(StackSave, "savedstack", 
+                                      FirstNewBlock->begin());
+    if (CG) CallerNode->addCalledFunction(SavedPtr, StackSaveCGN);
+      
     // Insert a call to llvm.stackrestore before any return instructions in the
     // inlined function.
-    for (unsigned i = 0, e = Returns.size(); i != e; ++i)
-      new CallInst(StackRestore, SavedPtr, "", Returns[i]);
+    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
+      CallInst *CI = new CallInst(StackRestore, SavedPtr, "", Returns[i]);
+      if (CG) CallerNode->addCalledFunction(CI, StackRestoreCGN);
+    }
 
     // Count the number of StackRestore calls we insert.
     unsigned NumStackRestores = Returns.size();
@@ -275,20 +304,6 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
           ++NumStackRestores;
         }
     }
-      
-    // If we are supposed to update the callgraph, do so now.
-    if (CG) {
-      CallGraphNode *StackSaveCGN    = CG->getOrInsertFunction(StackSave);
-      CallGraphNode *StackRestoreCGN = CG->getOrInsertFunction(StackRestore);
-      CallGraphNode *CallerNode = (*CG)[Caller];
-
-      // 'Caller' now calls llvm.stacksave one more time.
-      CallerNode->addCalledFunction(StackSaveCGN);
-      
-      // 'Caller' now calls llvm.stackrestore the appropriate number of times.
-      for (unsigned i = 0; i != NumStackRestores; ++i)
-        CallerNode->addCalledFunction(StackRestoreCGN);
-    }
   }
 
   // If we are inlining tail call instruction through a call site that isn't 
@@ -334,9 +349,6 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
     // Since we are now done with the return instruction, delete it also.
     Returns[0]->getParent()->getInstList().erase(Returns[0]);
 
-    // Update the callgraph if requested.
-    if (CG) UpdateCallGraphAfterInlining(Caller, CalledFunc, *CG);
-    
     // We are now done with the inlining.
     return true;
   }
@@ -463,8 +475,5 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) {
   // Now we can remove the CalleeEntry block, which is now empty.
   Caller->getBasicBlockList().erase(CalleeEntry);
   
-  // Update the callgraph if requested.
-  if (CG) UpdateCallGraphAfterInlining(Caller, CalledFunc, *CG);
-
   return true;
 }