10b57cec5SDimitry Andric //===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the CallGraphSCCPass class, which is used for passes 100b57cec5SDimitry Andric // which are implemented as bottom-up traversals on the call graph. Because 110b57cec5SDimitry Andric // there may be cycles in the call graph, passes of this type operate on the 120b57cec5SDimitry Andric // call-graph in SCC order: that is, they process function bottom-up, except for 130b57cec5SDimitry Andric // recursive functions, which they process all at once. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h" 180b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SCCIterator.h" 200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 2106c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 220b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h" 235ffd83dbSDimitry Andric #include "llvm/IR/AbstractCallSite.h" 240b57cec5SDimitry Andric #include "llvm/IR/Function.h" 250b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 260b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 270b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManagers.h" 280b57cec5SDimitry Andric #include "llvm/IR/Module.h" 290b57cec5SDimitry Andric #include "llvm/IR/OptBisect.h" 300b57cec5SDimitry Andric #include "llvm/IR/PassTimingInfo.h" 31e8d8bef9SDimitry Andric #include "llvm/IR/PrintPasses.h" 320b57cec5SDimitry Andric #include "llvm/Pass.h" 330b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 340b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 350b57cec5SDimitry Andric #include "llvm/Support/Timer.h" 360b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 370b57cec5SDimitry Andric #include <cassert> 380b57cec5SDimitry Andric #include <string> 390b57cec5SDimitry Andric #include <utility> 400b57cec5SDimitry Andric #include <vector> 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric using namespace llvm; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric #define DEBUG_TYPE "cgscc-passmgr" 450b57cec5SDimitry Andric 46fe6060f1SDimitry Andric namespace llvm { 47e8d8bef9SDimitry Andric cl::opt<unsigned> MaxDevirtIterations("max-devirt-iterations", cl::ReallyHidden, 48e8d8bef9SDimitry Andric cl::init(4)); 49*0fca6ea1SDimitry Andric } // namespace llvm 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC"); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 540b57cec5SDimitry Andric // CGPassManager 550b57cec5SDimitry Andric // 560b57cec5SDimitry Andric /// CGPassManager manages FPPassManagers and CallGraphSCCPasses. 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric namespace { 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric class CGPassManager : public ModulePass, public PMDataManager { 610b57cec5SDimitry Andric public: 620b57cec5SDimitry Andric static char ID; 630b57cec5SDimitry Andric 6404eeddc0SDimitry Andric explicit CGPassManager() : ModulePass(ID) {} 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /// Execute all of the passes scheduled for execution. Keep track of 670b57cec5SDimitry Andric /// whether any of the passes modifies the module, and if so, return true. 680b57cec5SDimitry Andric bool runOnModule(Module &M) override; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric using ModulePass::doInitialization; 710b57cec5SDimitry Andric using ModulePass::doFinalization; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric bool doInitialization(CallGraph &CG); 740b57cec5SDimitry Andric bool doFinalization(CallGraph &CG); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric /// Pass Manager itself does not invalidate any analysis info. 770b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &Info) const override { 780b57cec5SDimitry Andric // CGPassManager walks SCC and it needs CallGraph. 790b57cec5SDimitry Andric Info.addRequired<CallGraphWrapperPass>(); 800b57cec5SDimitry Andric Info.setPreservesAll(); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric StringRef getPassName() const override { return "CallGraph Pass Manager"; } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric PMDataManager *getAsPMDataManager() override { return this; } 860b57cec5SDimitry Andric Pass *getAsPass() override { return this; } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // Print passes managed by this manager 890b57cec5SDimitry Andric void dumpPassStructure(unsigned Offset) override { 900b57cec5SDimitry Andric errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n"; 910b57cec5SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { 920b57cec5SDimitry Andric Pass *P = getContainedPass(Index); 930b57cec5SDimitry Andric P->dumpPassStructure(Offset + 1); 940b57cec5SDimitry Andric dumpLastUses(P, Offset+1); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric Pass *getContainedPass(unsigned N) { 990b57cec5SDimitry Andric assert(N < PassVector.size() && "Pass number out of range!"); 1000b57cec5SDimitry Andric return static_cast<Pass *>(PassVector[N]); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric PassManagerType getPassManagerType() const override { 1040b57cec5SDimitry Andric return PMT_CallGraphPassManager; 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric private: 1080b57cec5SDimitry Andric bool RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG, 1090b57cec5SDimitry Andric bool &DevirtualizedCall); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, 1120b57cec5SDimitry Andric CallGraph &CG, bool &CallGraphUpToDate, 1130b57cec5SDimitry Andric bool &DevirtualizedCall); 1140b57cec5SDimitry Andric bool RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG, 1150b57cec5SDimitry Andric bool IsCheckingMode); 1160b57cec5SDimitry Andric }; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric } // end anonymous namespace. 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric char CGPassManager::ID = 0; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, 1230b57cec5SDimitry Andric CallGraph &CG, bool &CallGraphUpToDate, 1240b57cec5SDimitry Andric bool &DevirtualizedCall) { 1250b57cec5SDimitry Andric bool Changed = false; 1260b57cec5SDimitry Andric PMDataManager *PM = P->getAsPMDataManager(); 1270b57cec5SDimitry Andric Module &M = CG.getModule(); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric if (!PM) { 1300b57cec5SDimitry Andric CallGraphSCCPass *CGSP = (CallGraphSCCPass *)P; 1310b57cec5SDimitry Andric if (!CallGraphUpToDate) { 1320b57cec5SDimitry Andric DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false); 1330b57cec5SDimitry Andric CallGraphUpToDate = true; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric { 1370b57cec5SDimitry Andric unsigned InstrCount, SCCCount = 0; 1380b57cec5SDimitry Andric StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount; 1390b57cec5SDimitry Andric bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); 1400b57cec5SDimitry Andric TimeRegion PassTimer(getPassTimer(CGSP)); 1410b57cec5SDimitry Andric if (EmitICRemark) 1420b57cec5SDimitry Andric InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); 1430b57cec5SDimitry Andric Changed = CGSP->runOnSCC(CurSCC); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (EmitICRemark) { 1460b57cec5SDimitry Andric // FIXME: Add getInstructionCount to CallGraphSCC. 1470b57cec5SDimitry Andric SCCCount = M.getInstructionCount(); 1480b57cec5SDimitry Andric // Is there a difference in the number of instructions in the module? 1490b57cec5SDimitry Andric if (SCCCount != InstrCount) { 1500b57cec5SDimitry Andric // Yep. Emit a remark and update InstrCount. 1510b57cec5SDimitry Andric int64_t Delta = 1520b57cec5SDimitry Andric static_cast<int64_t>(SCCCount) - static_cast<int64_t>(InstrCount); 1530b57cec5SDimitry Andric emitInstrCountChangedRemark(P, M, Delta, InstrCount, 1540b57cec5SDimitry Andric FunctionToInstrCount); 1550b57cec5SDimitry Andric InstrCount = SCCCount; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // After the CGSCCPass is done, when assertions are enabled, use 1610b57cec5SDimitry Andric // RefreshCallGraph to verify that the callgraph was correctly updated. 1620b57cec5SDimitry Andric #ifndef NDEBUG 1630b57cec5SDimitry Andric if (Changed) 1640b57cec5SDimitry Andric RefreshCallGraph(CurSCC, CG, true); 1650b57cec5SDimitry Andric #endif 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric return Changed; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager && 1710b57cec5SDimitry Andric "Invalid CGPassManager member"); 1720b57cec5SDimitry Andric FPPassManager *FPP = (FPPassManager*)P; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // Run pass P on all functions in the current SCC. 1750b57cec5SDimitry Andric for (CallGraphNode *CGN : CurSCC) { 1760b57cec5SDimitry Andric if (Function *F = CGN->getFunction()) { 1770b57cec5SDimitry Andric dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); 1780b57cec5SDimitry Andric { 1790b57cec5SDimitry Andric TimeRegion PassTimer(getPassTimer(FPP)); 1800b57cec5SDimitry Andric Changed |= FPP->runOnFunction(*F); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric F->getContext().yield(); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // The function pass(es) modified the IR, they may have clobbered the 1870b57cec5SDimitry Andric // callgraph. 1880b57cec5SDimitry Andric if (Changed && CallGraphUpToDate) { 1890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Pass Dirtied SCC: " << P->getPassName() 1900b57cec5SDimitry Andric << '\n'); 1910b57cec5SDimitry Andric CallGraphUpToDate = false; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric return Changed; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric /// Scan the functions in the specified CFG and resync the 1970b57cec5SDimitry Andric /// callgraph with the call sites found in it. This is used after 1980b57cec5SDimitry Andric /// FunctionPasses have potentially munged the callgraph, and can be used after 1990b57cec5SDimitry Andric /// CallGraphSCC passes to verify that they correctly updated the callgraph. 2000b57cec5SDimitry Andric /// 2010b57cec5SDimitry Andric /// This function returns true if it devirtualized an existing function call, 2020b57cec5SDimitry Andric /// meaning it turned an indirect call into a direct call. This happens when 2030b57cec5SDimitry Andric /// a function pass like GVN optimizes away stuff feeding the indirect call. 2040b57cec5SDimitry Andric /// This never happens in checking mode. 2050b57cec5SDimitry Andric bool CGPassManager::RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG, 2060b57cec5SDimitry Andric bool CheckingMode) { 2070b57cec5SDimitry Andric DenseMap<Value *, CallGraphNode *> Calls; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size() 2100b57cec5SDimitry Andric << " nodes:\n"; 2110b57cec5SDimitry Andric for (CallGraphNode *CGN 2120b57cec5SDimitry Andric : CurSCC) CGN->dump();); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric bool MadeChange = false; 2150b57cec5SDimitry Andric bool DevirtualizedCall = false; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // Scan all functions in the SCC. 2180b57cec5SDimitry Andric unsigned FunctionNo = 0; 2190b57cec5SDimitry Andric for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end(); 2200b57cec5SDimitry Andric SCCIdx != E; ++SCCIdx, ++FunctionNo) { 2210b57cec5SDimitry Andric CallGraphNode *CGN = *SCCIdx; 2220b57cec5SDimitry Andric Function *F = CGN->getFunction(); 2230b57cec5SDimitry Andric if (!F || F->isDeclaration()) continue; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric // Walk the function body looking for call sites. Sync up the call sites in 2260b57cec5SDimitry Andric // CGN with those actually in the function. 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Keep track of the number of direct and indirect calls that were 2290b57cec5SDimitry Andric // invalidated and removed. 2300b57cec5SDimitry Andric unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0; 2310b57cec5SDimitry Andric 2325ffd83dbSDimitry Andric CallGraphNode::iterator CGNEnd = CGN->end(); 2335ffd83dbSDimitry Andric 2345ffd83dbSDimitry Andric auto RemoveAndCheckForDone = [&](CallGraphNode::iterator I) { 2355ffd83dbSDimitry Andric // Just remove the edge from the set of callees, keep track of whether 2365ffd83dbSDimitry Andric // I points to the last element of the vector. 2375ffd83dbSDimitry Andric bool WasLast = I + 1 == CGNEnd; 2385ffd83dbSDimitry Andric CGN->removeCallEdge(I); 2395ffd83dbSDimitry Andric 2405ffd83dbSDimitry Andric // If I pointed to the last element of the vector, we have to bail out: 2415ffd83dbSDimitry Andric // iterator checking rejects comparisons of the resultant pointer with 2425ffd83dbSDimitry Andric // end. 2435ffd83dbSDimitry Andric if (WasLast) 2445ffd83dbSDimitry Andric return true; 2455ffd83dbSDimitry Andric 2465ffd83dbSDimitry Andric CGNEnd = CGN->end(); 2475ffd83dbSDimitry Andric return false; 2485ffd83dbSDimitry Andric }; 2495ffd83dbSDimitry Andric 2500b57cec5SDimitry Andric // Get the set of call sites currently in the function. 2515ffd83dbSDimitry Andric for (CallGraphNode::iterator I = CGN->begin(); I != CGNEnd;) { 2525ffd83dbSDimitry Andric // Delete "reference" call records that do not have call instruction. We 2535ffd83dbSDimitry Andric // reinsert them as needed later. However, keep them in checking mode. 2545ffd83dbSDimitry Andric if (!I->first) { 2555ffd83dbSDimitry Andric if (CheckingMode) { 2565ffd83dbSDimitry Andric ++I; 2575ffd83dbSDimitry Andric continue; 2585ffd83dbSDimitry Andric } 2595ffd83dbSDimitry Andric if (RemoveAndCheckForDone(I)) 2605ffd83dbSDimitry Andric break; 2615ffd83dbSDimitry Andric continue; 2625ffd83dbSDimitry Andric } 2635ffd83dbSDimitry Andric 2640b57cec5SDimitry Andric // If this call site is null, then the function pass deleted the call 2650b57cec5SDimitry Andric // entirely and the WeakTrackingVH nulled it out. 2665ffd83dbSDimitry Andric auto *Call = dyn_cast_or_null<CallBase>(*I->first); 2675ffd83dbSDimitry Andric if (!Call || 2680b57cec5SDimitry Andric // If we've already seen this call site, then the FunctionPass RAUW'd 2690b57cec5SDimitry Andric // one call with another, which resulted in two "uses" in the edge 2700b57cec5SDimitry Andric // list of the same call. 271bdd1243dSDimitry Andric Calls.count(Call)) { 2720b57cec5SDimitry Andric assert(!CheckingMode && 2730b57cec5SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!"); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // If this was an indirect call site, count it. 2760b57cec5SDimitry Andric if (!I->second->getFunction()) 2770b57cec5SDimitry Andric ++NumIndirectRemoved; 2780b57cec5SDimitry Andric else 2790b57cec5SDimitry Andric ++NumDirectRemoved; 2800b57cec5SDimitry Andric 2815ffd83dbSDimitry Andric if (RemoveAndCheckForDone(I)) 2820b57cec5SDimitry Andric break; 2830b57cec5SDimitry Andric continue; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2865ffd83dbSDimitry Andric assert(!Calls.count(Call) && "Call site occurs in node multiple times"); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric if (Call) { 2890b57cec5SDimitry Andric Function *Callee = Call->getCalledFunction(); 2900b57cec5SDimitry Andric // Ignore intrinsics because they're not really function calls. 2910b57cec5SDimitry Andric if (!Callee || !(Callee->isIntrinsic())) 2925ffd83dbSDimitry Andric Calls.insert(std::make_pair(Call, I->second)); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric ++I; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric // Loop over all of the instructions in the function, getting the callsites. 2980b57cec5SDimitry Andric // Keep track of the number of direct/indirect calls added. 2990b57cec5SDimitry Andric unsigned NumDirectAdded = 0, NumIndirectAdded = 0; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric for (BasicBlock &BB : *F) 3020b57cec5SDimitry Andric for (Instruction &I : BB) { 3030b57cec5SDimitry Andric auto *Call = dyn_cast<CallBase>(&I); 3040b57cec5SDimitry Andric if (!Call) 3050b57cec5SDimitry Andric continue; 3060b57cec5SDimitry Andric Function *Callee = Call->getCalledFunction(); 3070b57cec5SDimitry Andric if (Callee && Callee->isIntrinsic()) 3080b57cec5SDimitry Andric continue; 3090b57cec5SDimitry Andric 3105ffd83dbSDimitry Andric // If we are not in checking mode, insert potential callback calls as 3115ffd83dbSDimitry Andric // references. This is not a requirement but helps to iterate over the 3125ffd83dbSDimitry Andric // functions in the right order. 3135ffd83dbSDimitry Andric if (!CheckingMode) { 3145ffd83dbSDimitry Andric forEachCallbackFunction(*Call, [&](Function *CB) { 3155ffd83dbSDimitry Andric CGN->addCalledFunction(nullptr, CG.getOrInsertFunction(CB)); 3165ffd83dbSDimitry Andric }); 3175ffd83dbSDimitry Andric } 3185ffd83dbSDimitry Andric 3190b57cec5SDimitry Andric // If this call site already existed in the callgraph, just verify it 3200b57cec5SDimitry Andric // matches up to expectations and remove it from Calls. 3210b57cec5SDimitry Andric DenseMap<Value *, CallGraphNode *>::iterator ExistingIt = 3220b57cec5SDimitry Andric Calls.find(Call); 3230b57cec5SDimitry Andric if (ExistingIt != Calls.end()) { 3240b57cec5SDimitry Andric CallGraphNode *ExistingNode = ExistingIt->second; 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric // Remove from Calls since we have now seen it. 3270b57cec5SDimitry Andric Calls.erase(ExistingIt); 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // Verify that the callee is right. 3300b57cec5SDimitry Andric if (ExistingNode->getFunction() == Call->getCalledFunction()) 3310b57cec5SDimitry Andric continue; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric // If we are in checking mode, we are not allowed to actually mutate 3340b57cec5SDimitry Andric // the callgraph. If this is a case where we can infer that the 3350b57cec5SDimitry Andric // callgraph is less precise than it could be (e.g. an indirect call 3360b57cec5SDimitry Andric // site could be turned direct), don't reject it in checking mode, and 3370b57cec5SDimitry Andric // don't tweak it to be more precise. 3380b57cec5SDimitry Andric if (CheckingMode && Call->getCalledFunction() && 3390b57cec5SDimitry Andric ExistingNode->getFunction() == nullptr) 3400b57cec5SDimitry Andric continue; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric assert(!CheckingMode && 3430b57cec5SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!"); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // If not, we either went from a direct call to indirect, indirect to 3460b57cec5SDimitry Andric // direct, or direct to different direct. 3470b57cec5SDimitry Andric CallGraphNode *CalleeNode; 3480b57cec5SDimitry Andric if (Function *Callee = Call->getCalledFunction()) { 3490b57cec5SDimitry Andric CalleeNode = CG.getOrInsertFunction(Callee); 3500b57cec5SDimitry Andric // Keep track of whether we turned an indirect call into a direct 3510b57cec5SDimitry Andric // one. 3520b57cec5SDimitry Andric if (!ExistingNode->getFunction()) { 3530b57cec5SDimitry Andric DevirtualizedCall = true; 3540b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Devirtualized call to '" 3550b57cec5SDimitry Andric << Callee->getName() << "'\n"); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric } else { 3580b57cec5SDimitry Andric CalleeNode = CG.getCallsExternalNode(); 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // Update the edge target in CGN. 3620b57cec5SDimitry Andric CGN->replaceCallEdge(*Call, *Call, CalleeNode); 3630b57cec5SDimitry Andric MadeChange = true; 3640b57cec5SDimitry Andric continue; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric assert(!CheckingMode && 3680b57cec5SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!"); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // If the call site didn't exist in the CGN yet, add it. 3710b57cec5SDimitry Andric CallGraphNode *CalleeNode; 3720b57cec5SDimitry Andric if (Function *Callee = Call->getCalledFunction()) { 3730b57cec5SDimitry Andric CalleeNode = CG.getOrInsertFunction(Callee); 3740b57cec5SDimitry Andric ++NumDirectAdded; 3750b57cec5SDimitry Andric } else { 3760b57cec5SDimitry Andric CalleeNode = CG.getCallsExternalNode(); 3770b57cec5SDimitry Andric ++NumIndirectAdded; 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric CGN->addCalledFunction(Call, CalleeNode); 3810b57cec5SDimitry Andric MadeChange = true; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // We scanned the old callgraph node, removing invalidated call sites and 3850b57cec5SDimitry Andric // then added back newly found call sites. One thing that can happen is 3860b57cec5SDimitry Andric // that an old indirect call site was deleted and replaced with a new direct 3870b57cec5SDimitry Andric // call. In this case, we have devirtualized a call, and CGSCCPM would like 3880b57cec5SDimitry Andric // to iteratively optimize the new code. Unfortunately, we don't really 3890b57cec5SDimitry Andric // have a great way to detect when this happens. As an approximation, we 3900b57cec5SDimitry Andric // just look at whether the number of indirect calls is reduced and the 3910b57cec5SDimitry Andric // number of direct calls is increased. There are tons of ways to fool this 3920b57cec5SDimitry Andric // (e.g. DCE'ing an indirect call and duplicating an unrelated block with a 3930b57cec5SDimitry Andric // direct call) but this is close enough. 3940b57cec5SDimitry Andric if (NumIndirectRemoved > NumIndirectAdded && 3950b57cec5SDimitry Andric NumDirectRemoved < NumDirectAdded) 3960b57cec5SDimitry Andric DevirtualizedCall = true; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric // After scanning this function, if we still have entries in callsites, then 3990b57cec5SDimitry Andric // they are dangling pointers. WeakTrackingVH should save us for this, so 4000b57cec5SDimitry Andric // abort if 4010b57cec5SDimitry Andric // this happens. 4020b57cec5SDimitry Andric assert(Calls.empty() && "Dangling pointers found in call sites map"); 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // Periodically do an explicit clear to remove tombstones when processing 4050b57cec5SDimitry Andric // large scc's. 4060b57cec5SDimitry Andric if ((FunctionNo & 15) == 15) 4070b57cec5SDimitry Andric Calls.clear(); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric LLVM_DEBUG(if (MadeChange) { 4110b57cec5SDimitry Andric dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n"; 4120b57cec5SDimitry Andric for (CallGraphNode *CGN : CurSCC) 4130b57cec5SDimitry Andric CGN->dump(); 4140b57cec5SDimitry Andric if (DevirtualizedCall) 4150b57cec5SDimitry Andric dbgs() << "CGSCCPASSMGR: Refresh devirtualized a call!\n"; 4160b57cec5SDimitry Andric } else { 4170b57cec5SDimitry Andric dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n"; 4180b57cec5SDimitry Andric }); 4190b57cec5SDimitry Andric (void)MadeChange; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric return DevirtualizedCall; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric /// Execute the body of the entire pass manager on the specified SCC. 4250b57cec5SDimitry Andric /// This keeps track of whether a function pass devirtualizes 4260b57cec5SDimitry Andric /// any calls and returns it in DevirtualizedCall. 4270b57cec5SDimitry Andric bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG, 4280b57cec5SDimitry Andric bool &DevirtualizedCall) { 4290b57cec5SDimitry Andric bool Changed = false; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Keep track of whether the callgraph is known to be up-to-date or not. 4320b57cec5SDimitry Andric // The CGSSC pass manager runs two types of passes: 4330b57cec5SDimitry Andric // CallGraphSCC Passes and other random function passes. Because other 4340b57cec5SDimitry Andric // random function passes are not CallGraph aware, they may clobber the 4350b57cec5SDimitry Andric // call graph by introducing new calls or deleting other ones. This flag 4360b57cec5SDimitry Andric // is set to false when we run a function pass so that we know to clean up 4370b57cec5SDimitry Andric // the callgraph when we need to run a CGSCCPass again. 4380b57cec5SDimitry Andric bool CallGraphUpToDate = true; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric // Run all passes on current SCC. 4410b57cec5SDimitry Andric for (unsigned PassNo = 0, e = getNumContainedPasses(); 4420b57cec5SDimitry Andric PassNo != e; ++PassNo) { 4430b57cec5SDimitry Andric Pass *P = getContainedPass(PassNo); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric // If we're in -debug-pass=Executions mode, construct the SCC node list, 4460b57cec5SDimitry Andric // otherwise avoid constructing this string as it is expensive. 4470b57cec5SDimitry Andric if (isPassDebuggingExecutionsOrMore()) { 4480b57cec5SDimitry Andric std::string Functions; 4490b57cec5SDimitry Andric #ifndef NDEBUG 4500b57cec5SDimitry Andric raw_string_ostream OS(Functions); 451fe6060f1SDimitry Andric ListSeparator LS; 452fe6060f1SDimitry Andric for (const CallGraphNode *CGN : CurSCC) { 453fe6060f1SDimitry Andric OS << LS; 454fe6060f1SDimitry Andric CGN->print(OS); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric OS.flush(); 4570b57cec5SDimitry Andric #endif 4580b57cec5SDimitry Andric dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric dumpRequiredSet(P); 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric initializeAnalysisImpl(P); 4630b57cec5SDimitry Andric 464e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS 46581ad6265SDimitry Andric uint64_t RefHash = P->structuralHash(CG.getModule()); 466e8d8bef9SDimitry Andric #endif 4670b57cec5SDimitry Andric 468e8d8bef9SDimitry Andric // Actually run this pass on the current SCC. 469e8d8bef9SDimitry Andric bool LocalChanged = 470e8d8bef9SDimitry Andric RunPassOnSCC(P, CurSCC, CG, CallGraphUpToDate, DevirtualizedCall); 471e8d8bef9SDimitry Andric 472e8d8bef9SDimitry Andric Changed |= LocalChanged; 473e8d8bef9SDimitry Andric 474e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS 47581ad6265SDimitry Andric if (!LocalChanged && (RefHash != P->structuralHash(CG.getModule()))) { 476e8d8bef9SDimitry Andric llvm::errs() << "Pass modifies its input and doesn't report it: " 477e8d8bef9SDimitry Andric << P->getPassName() << "\n"; 478e8d8bef9SDimitry Andric llvm_unreachable("Pass modifies its input and doesn't report it"); 479e8d8bef9SDimitry Andric } 480e8d8bef9SDimitry Andric #endif 481e8d8bef9SDimitry Andric if (LocalChanged) 4820b57cec5SDimitry Andric dumpPassInfo(P, MODIFICATION_MSG, ON_CG_MSG, ""); 4830b57cec5SDimitry Andric dumpPreservedSet(P); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric verifyPreservedAnalysis(P); 486e8d8bef9SDimitry Andric if (LocalChanged) 4870b57cec5SDimitry Andric removeNotPreservedAnalysis(P); 4880b57cec5SDimitry Andric recordAvailableAnalysis(P); 4890b57cec5SDimitry Andric removeDeadPasses(P, "", ON_CG_MSG); 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric // If the callgraph was left out of date (because the last pass run was a 4930b57cec5SDimitry Andric // functionpass), refresh it before we move on to the next SCC. 4940b57cec5SDimitry Andric if (!CallGraphUpToDate) 4950b57cec5SDimitry Andric DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false); 4960b57cec5SDimitry Andric return Changed; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric /// Execute all of the passes scheduled for execution. Keep track of 5000b57cec5SDimitry Andric /// whether any of the passes modifies the module, and if so, return true. 5010b57cec5SDimitry Andric bool CGPassManager::runOnModule(Module &M) { 5020b57cec5SDimitry Andric CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); 5030b57cec5SDimitry Andric bool Changed = doInitialization(CG); 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric // Walk the callgraph in bottom-up SCC order. 5060b57cec5SDimitry Andric scc_iterator<CallGraph*> CGI = scc_begin(&CG); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric CallGraphSCC CurSCC(CG, &CGI); 5090b57cec5SDimitry Andric while (!CGI.isAtEnd()) { 5100b57cec5SDimitry Andric // Copy the current SCC and increment past it so that the pass can hack 5110b57cec5SDimitry Andric // on the SCC if it wants to without invalidating our iterator. 5120b57cec5SDimitry Andric const std::vector<CallGraphNode *> &NodeVec = *CGI; 5130b57cec5SDimitry Andric CurSCC.initialize(NodeVec); 5140b57cec5SDimitry Andric ++CGI; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric // At the top level, we run all the passes in this pass manager on the 5170b57cec5SDimitry Andric // functions in this SCC. However, we support iterative compilation in the 5180b57cec5SDimitry Andric // case where a function pass devirtualizes a call to a function. For 5190b57cec5SDimitry Andric // example, it is very common for a function pass (often GVN or instcombine) 5200b57cec5SDimitry Andric // to eliminate the addressing that feeds into a call. With that improved 5210b57cec5SDimitry Andric // information, we would like the call to be an inline candidate, infer 5220b57cec5SDimitry Andric // mod-ref information etc. 5230b57cec5SDimitry Andric // 5240b57cec5SDimitry Andric // Because of this, we allow iteration up to a specified iteration count. 5250b57cec5SDimitry Andric // This only happens in the case of a devirtualized call, so we only burn 5260b57cec5SDimitry Andric // compile time in the case that we're making progress. We also have a hard 5270b57cec5SDimitry Andric // iteration count limit in case there is crazy code. 5280b57cec5SDimitry Andric unsigned Iteration = 0; 5290b57cec5SDimitry Andric bool DevirtualizedCall = false; 5300b57cec5SDimitry Andric do { 5310b57cec5SDimitry Andric LLVM_DEBUG(if (Iteration) dbgs() 5320b57cec5SDimitry Andric << " SCCPASSMGR: Re-visiting SCC, iteration #" << Iteration 5330b57cec5SDimitry Andric << '\n'); 5340b57cec5SDimitry Andric DevirtualizedCall = false; 5350b57cec5SDimitry Andric Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall); 536e8d8bef9SDimitry Andric } while (Iteration++ < MaxDevirtIterations && DevirtualizedCall); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric if (DevirtualizedCall) 5390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Stopped iteration after " 5400b57cec5SDimitry Andric << Iteration 541e8d8bef9SDimitry Andric << " times, due to -max-devirt-iterations\n"); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric MaxSCCIterations.updateMax(Iteration); 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric Changed |= doFinalization(CG); 5460b57cec5SDimitry Andric return Changed; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric /// Initialize CG 5500b57cec5SDimitry Andric bool CGPassManager::doInitialization(CallGraph &CG) { 5510b57cec5SDimitry Andric bool Changed = false; 5520b57cec5SDimitry Andric for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { 5530b57cec5SDimitry Andric if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { 5540b57cec5SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager && 5550b57cec5SDimitry Andric "Invalid CGPassManager member"); 5560b57cec5SDimitry Andric Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule()); 5570b57cec5SDimitry Andric } else { 5580b57cec5SDimitry Andric Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric return Changed; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric /// Finalize CG 5650b57cec5SDimitry Andric bool CGPassManager::doFinalization(CallGraph &CG) { 5660b57cec5SDimitry Andric bool Changed = false; 5670b57cec5SDimitry Andric for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { 5680b57cec5SDimitry Andric if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { 5690b57cec5SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager && 5700b57cec5SDimitry Andric "Invalid CGPassManager member"); 5710b57cec5SDimitry Andric Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule()); 5720b57cec5SDimitry Andric } else { 5730b57cec5SDimitry Andric Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric return Changed; 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5800b57cec5SDimitry Andric // CallGraphSCC Implementation 5810b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric /// This informs the SCC and the pass manager that the specified 5840b57cec5SDimitry Andric /// Old node has been deleted, and New is to be used in its place. 5850b57cec5SDimitry Andric void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) { 5860b57cec5SDimitry Andric assert(Old != New && "Should not replace node with self"); 5870b57cec5SDimitry Andric for (unsigned i = 0; ; ++i) { 5880b57cec5SDimitry Andric assert(i != Nodes.size() && "Node not in SCC"); 5890b57cec5SDimitry Andric if (Nodes[i] != Old) continue; 5905ffd83dbSDimitry Andric if (New) 5910b57cec5SDimitry Andric Nodes[i] = New; 5925ffd83dbSDimitry Andric else 5935ffd83dbSDimitry Andric Nodes.erase(Nodes.begin() + i); 5940b57cec5SDimitry Andric break; 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric // Update the active scc_iterator so that it doesn't contain dangling 5980b57cec5SDimitry Andric // pointers to the old CallGraphNode. 5990b57cec5SDimitry Andric scc_iterator<CallGraph*> *CGI = (scc_iterator<CallGraph*>*)Context; 6000b57cec5SDimitry Andric CGI->ReplaceNode(Old, New); 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6035ffd83dbSDimitry Andric void CallGraphSCC::DeleteNode(CallGraphNode *Old) { 6045ffd83dbSDimitry Andric ReplaceNode(Old, /*New=*/nullptr); 6055ffd83dbSDimitry Andric } 6065ffd83dbSDimitry Andric 6070b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6080b57cec5SDimitry Andric // CallGraphSCCPass Implementation 6090b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric /// Assign pass manager to manage this pass. 6120b57cec5SDimitry Andric void CallGraphSCCPass::assignPassManager(PMStack &PMS, 6130b57cec5SDimitry Andric PassManagerType PreferredType) { 6140b57cec5SDimitry Andric // Find CGPassManager 6150b57cec5SDimitry Andric while (!PMS.empty() && 6160b57cec5SDimitry Andric PMS.top()->getPassManagerType() > PMT_CallGraphPassManager) 6170b57cec5SDimitry Andric PMS.pop(); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric assert(!PMS.empty() && "Unable to handle Call Graph Pass"); 6200b57cec5SDimitry Andric CGPassManager *CGP; 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager) 6230b57cec5SDimitry Andric CGP = (CGPassManager*)PMS.top(); 6240b57cec5SDimitry Andric else { 6250b57cec5SDimitry Andric // Create new Call Graph SCC Pass Manager if it does not exist. 6260b57cec5SDimitry Andric assert(!PMS.empty() && "Unable to create Call Graph Pass Manager"); 6270b57cec5SDimitry Andric PMDataManager *PMD = PMS.top(); 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric // [1] Create new Call Graph Pass Manager 6300b57cec5SDimitry Andric CGP = new CGPassManager(); 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric // [2] Set up new manager's top level manager 6330b57cec5SDimitry Andric PMTopLevelManager *TPM = PMD->getTopLevelManager(); 6340b57cec5SDimitry Andric TPM->addIndirectPassManager(CGP); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric // [3] Assign manager to manage this new manager. This may create 6370b57cec5SDimitry Andric // and push new managers into PMS 6380b57cec5SDimitry Andric Pass *P = CGP; 6390b57cec5SDimitry Andric TPM->schedulePass(P); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric // [4] Push new manager into PMS 6420b57cec5SDimitry Andric PMS.push(CGP); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric CGP->add(this); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric /// For this class, we declare that we require and preserve the call graph. 6490b57cec5SDimitry Andric /// If the derived class implements this method, it should 6500b57cec5SDimitry Andric /// always explicitly call the implementation here. 6510b57cec5SDimitry Andric void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const { 6520b57cec5SDimitry Andric AU.addRequired<CallGraphWrapperPass>(); 6530b57cec5SDimitry Andric AU.addPreserved<CallGraphWrapperPass>(); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6570b57cec5SDimitry Andric // PrintCallGraphPass Implementation 6580b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric namespace { 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric /// PrintCallGraphPass - Print a Module corresponding to a call graph. 6630b57cec5SDimitry Andric /// 6640b57cec5SDimitry Andric class PrintCallGraphPass : public CallGraphSCCPass { 6650b57cec5SDimitry Andric std::string Banner; 6660b57cec5SDimitry Andric raw_ostream &OS; // raw_ostream to print on. 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric public: 6690b57cec5SDimitry Andric static char ID; 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric PrintCallGraphPass(const std::string &B, raw_ostream &OS) 6720b57cec5SDimitry Andric : CallGraphSCCPass(ID), Banner(B), OS(OS) {} 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 6750b57cec5SDimitry Andric AU.setPreservesAll(); 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric bool runOnSCC(CallGraphSCC &SCC) override { 6790b57cec5SDimitry Andric bool BannerPrinted = false; 6800b57cec5SDimitry Andric auto PrintBannerOnce = [&]() { 6810b57cec5SDimitry Andric if (BannerPrinted) 6820b57cec5SDimitry Andric return; 6830b57cec5SDimitry Andric OS << Banner; 6840b57cec5SDimitry Andric BannerPrinted = true; 6850b57cec5SDimitry Andric }; 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric bool NeedModule = llvm::forcePrintModuleIR(); 6880b57cec5SDimitry Andric if (isFunctionInPrintList("*") && NeedModule) { 6890b57cec5SDimitry Andric PrintBannerOnce(); 6900b57cec5SDimitry Andric OS << "\n"; 6910b57cec5SDimitry Andric SCC.getCallGraph().getModule().print(OS, nullptr); 6920b57cec5SDimitry Andric return false; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric bool FoundFunction = false; 6950b57cec5SDimitry Andric for (CallGraphNode *CGN : SCC) { 6960b57cec5SDimitry Andric if (Function *F = CGN->getFunction()) { 6970b57cec5SDimitry Andric if (!F->isDeclaration() && isFunctionInPrintList(F->getName())) { 6980b57cec5SDimitry Andric FoundFunction = true; 6990b57cec5SDimitry Andric if (!NeedModule) { 7000b57cec5SDimitry Andric PrintBannerOnce(); 7010b57cec5SDimitry Andric F->print(OS); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric } else if (isFunctionInPrintList("*")) { 7050b57cec5SDimitry Andric PrintBannerOnce(); 7060b57cec5SDimitry Andric OS << "\nPrinting <null> Function\n"; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric if (NeedModule && FoundFunction) { 7100b57cec5SDimitry Andric PrintBannerOnce(); 7110b57cec5SDimitry Andric OS << "\n"; 7120b57cec5SDimitry Andric SCC.getCallGraph().getModule().print(OS, nullptr); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric return false; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric StringRef getPassName() const override { return "Print CallGraph IR"; } 7180b57cec5SDimitry Andric }; 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric } // end anonymous namespace. 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric char PrintCallGraphPass::ID = 0; 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric Pass *CallGraphSCCPass::createPrinterPass(raw_ostream &OS, 7250b57cec5SDimitry Andric const std::string &Banner) const { 7260b57cec5SDimitry Andric return new PrintCallGraphPass(Banner, OS); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric static std::string getDescription(const CallGraphSCC &SCC) { 7300b57cec5SDimitry Andric std::string Desc = "SCC ("; 731fe6060f1SDimitry Andric ListSeparator LS; 7320b57cec5SDimitry Andric for (CallGraphNode *CGN : SCC) { 733fe6060f1SDimitry Andric Desc += LS; 7340b57cec5SDimitry Andric Function *F = CGN->getFunction(); 7350b57cec5SDimitry Andric if (F) 7360b57cec5SDimitry Andric Desc += F->getName(); 7370b57cec5SDimitry Andric else 7380b57cec5SDimitry Andric Desc += "<<null function>>"; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric Desc += ")"; 7410b57cec5SDimitry Andric return Desc; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric bool CallGraphSCCPass::skipSCC(CallGraphSCC &SCC) const { 7450b57cec5SDimitry Andric OptPassGate &Gate = 7460b57cec5SDimitry Andric SCC.getCallGraph().getModule().getContext().getOptPassGate(); 747bdd1243dSDimitry Andric return Gate.isEnabled() && 748bdd1243dSDimitry Andric !Gate.shouldRunPass(this->getPassName(), getDescription(SCC)); 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric char DummyCGSCCPass::ID = 0; 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false, 7540b57cec5SDimitry Andric false) 755