diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 94cea100485..b567bab474f 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -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 CalledFunctions; + typedef std::pair CallRecord; + std::vector CalledFunctions; CallGraphNode(const CallGraphNode &); // Do not implement public: @@ -175,8 +177,8 @@ public: // Accessor methods... // - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; + typedef std::vector::iterator iterator; + typedef std::vector::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 { typedef CallGraphNode NodeType; - typedef NodeType::iterator ChildIteratorType; + typedef std::pair CGNPairTy; + typedef std::pointer_to_unary_function 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 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 { @@ -270,8 +288,7 @@ template<> struct GraphTraits : public GraphTraits { return map_iterator(CG->end(), DerefFun(CGdereference)); } - static CallGraphNode &CGdereference (std::pair P) { + static CallGraphNode &CGdereference(PairTy P) { return *P.second; } }; diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index 78bb735ffa2..23a7599ce57 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -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(*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(*I)) { for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) if (Instruction *Inst = dyn_cast(*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 <>:\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; diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index 5b3c953bcdf..4765b096b38 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -263,7 +263,7 @@ void GlobalsModRef::AnalyzeSCC(std::vector &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; diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 89999bb4425..ae4032bbfb3 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -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 diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 37ba3ba6d49..277b10a767f 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -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 &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::iterator VMI = ValueMap.find(OrigCall); + if (VMI != ValueMap.end()) { // Only copy the edge if the call was inlined! + Instruction *NewCall = cast(VMI->second); + CallerNode->addCalledFunction(CallSite::get(NewCall), I->second); + } + } } @@ -192,6 +202,8 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG) { // function. std::vector Returns; ClonedCodeInfo InlinedFunctionInfo; + Function::iterator FirstNewBlock; + { // Scope to destroy ValueMap after cloning. std::map 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; }