/// Scan the functions in the specified CFG and resync the /// callgraph with the call sites found in it. This is used after /// FunctionPasses have potentially munged the callgraph, and can be used after /// CallGraphSCC passes to verify that they correctly updated the callgraph. /// /// This function returns true if it devirtualized an existing function call, /// meaning it turned an indirect call into a direct call. This happens when /// a function pass like GVN optimizes away stuff feeding the indirect call. /// This never happens in checking mode. bool CGPassManager::RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG, bool CheckingMode) { DenseMap<Value*, CallGraphNode*> CallSites; LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size() << " nodes:\n"; for (CallGraphNode *CGN : CurSCC) CGN->dump(););
/// RefreshCallGraph - Scan the functions in the specified CFG and resync the /// callgraph with the call sites found in it. This is used after /// FunctionPasses have potentially munged the callgraph, and can be used after /// CallGraphSCC passes to verify that they correctly updated the callgraph. /// /// This function returns true if it devirtualized an existing function call, /// meaning it turned an indirect call into a direct call. This happens when /// a function pass like GVN optimizes away stuff feeding the indirect call. /// This never happens in checking mode. /// bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, CallGraph &CG, bool CheckingMode) { DenseMap<Value*, CallGraphNode*> CallSites; DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size() << " nodes:\n"; for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end(); I != E; ++I) (*I)->dump(); );
bool BottomUpPass::runOnSCC(CallGraphSCC &SCC) { // NumCalls =0; // CallGraph CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); //DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>(); //const DataLayout *DL = DLP ? &DLP->getDataLayout() : nullptr; //const TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>(); SmallPtrSet<Function*, 8> SCCFunctions; DEBUG(dbgs() << "\nInliner visiting SCC:"); for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { Function *F = (*I)->getFunction(); if (F) {SCCFunctions.insert(F); NumFuncitons++; } DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE")); } // NumCalls = SCCFunctions.size(); DEBUG(dbgs() << "\nSizeof the SCC: "<<SCC.size()); //Collect all the call sites. SmallVector<std::pair<CallSite, int>, 16> CallSites; for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { Function *F = (*I)->getFunction(); if (!F) { //Check waht kind of call it is: // errs()<<"\nCallGRaph node dump -- "; // (*I)->dump(); continue; } for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { CallSite CS(cast<Value>(I)); // If this isn't a call, or it is a call to an intrinsic, it can // never be inlined. if (!CS || isa<IntrinsicInst>(I)) continue; // If this is a direct call to an external function, we can never inline // it. If it is an indirect call, inlining may resolve it to be a // direct call, so we keep it. if (CS.getCalledFunction() && CS.getCalledFunction()->isDeclaration()) continue; CallSites.push_back(std::make_pair(CS, -1)); } } DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n"); NumCalls +=CallSites.size(); }