llvm-project
754 строки · 26.3 Кб
1//===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the CallGraphSCCPass class, which is used for passes
10// which are implemented as bottom-up traversals on the call graph. Because
11// there may be cycles in the call graph, passes of this type operate on the
12// call-graph in SCC order: that is, they process function bottom-up, except for
13// recursive functions, which they process all at once.
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/Analysis/CallGraphSCCPass.h"18#include "llvm/ADT/DenseMap.h"19#include "llvm/ADT/SCCIterator.h"20#include "llvm/ADT/Statistic.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/Analysis/CallGraph.h"23#include "llvm/IR/AbstractCallSite.h"24#include "llvm/IR/Function.h"25#include "llvm/IR/Intrinsics.h"26#include "llvm/IR/LLVMContext.h"27#include "llvm/IR/LegacyPassManagers.h"28#include "llvm/IR/Module.h"29#include "llvm/IR/OptBisect.h"30#include "llvm/IR/PassTimingInfo.h"31#include "llvm/IR/PrintPasses.h"32#include "llvm/Pass.h"33#include "llvm/Support/CommandLine.h"34#include "llvm/Support/Debug.h"35#include "llvm/Support/Timer.h"36#include "llvm/Support/raw_ostream.h"37#include <cassert>38#include <string>39#include <utility>40#include <vector>41
42using namespace llvm;43
44#define DEBUG_TYPE "cgscc-passmgr"45
46namespace llvm {47cl::opt<unsigned> MaxDevirtIterations("max-devirt-iterations", cl::ReallyHidden,48cl::init(4));49} // namespace llvm50
51STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC");52
53//===----------------------------------------------------------------------===//
54// CGPassManager
55//
56/// CGPassManager manages FPPassManagers and CallGraphSCCPasses.
57
58namespace {59
60class CGPassManager : public ModulePass, public PMDataManager {61public:62static char ID;63
64explicit CGPassManager() : ModulePass(ID) {}65
66/// Execute all of the passes scheduled for execution. Keep track of67/// whether any of the passes modifies the module, and if so, return true.68bool runOnModule(Module &M) override;69
70using ModulePass::doInitialization;71using ModulePass::doFinalization;72
73bool doInitialization(CallGraph &CG);74bool doFinalization(CallGraph &CG);75
76/// Pass Manager itself does not invalidate any analysis info.77void getAnalysisUsage(AnalysisUsage &Info) const override {78// CGPassManager walks SCC and it needs CallGraph.79Info.addRequired<CallGraphWrapperPass>();80Info.setPreservesAll();81}82
83StringRef getPassName() const override { return "CallGraph Pass Manager"; }84
85PMDataManager *getAsPMDataManager() override { return this; }86Pass *getAsPass() override { return this; }87
88// Print passes managed by this manager89void dumpPassStructure(unsigned Offset) override {90errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n";91for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {92Pass *P = getContainedPass(Index);93P->dumpPassStructure(Offset + 1);94dumpLastUses(P, Offset+1);95}96}97
98Pass *getContainedPass(unsigned N) {99assert(N < PassVector.size() && "Pass number out of range!");100return static_cast<Pass *>(PassVector[N]);101}102
103PassManagerType getPassManagerType() const override {104return PMT_CallGraphPassManager;105}106
107private:108bool RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,109bool &DevirtualizedCall);110
111bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,112CallGraph &CG, bool &CallGraphUpToDate,113bool &DevirtualizedCall);114bool RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG,115bool IsCheckingMode);116};117
118} // end anonymous namespace.119
120char CGPassManager::ID = 0;121
122bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,123CallGraph &CG, bool &CallGraphUpToDate,124bool &DevirtualizedCall) {125bool Changed = false;126PMDataManager *PM = P->getAsPMDataManager();127Module &M = CG.getModule();128
129if (!PM) {130CallGraphSCCPass *CGSP = (CallGraphSCCPass *)P;131if (!CallGraphUpToDate) {132DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false);133CallGraphUpToDate = true;134}135
136{137unsigned InstrCount, SCCCount = 0;138StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount;139bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();140TimeRegion PassTimer(getPassTimer(CGSP));141if (EmitICRemark)142InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);143Changed = CGSP->runOnSCC(CurSCC);144
145if (EmitICRemark) {146// FIXME: Add getInstructionCount to CallGraphSCC.147SCCCount = M.getInstructionCount();148// Is there a difference in the number of instructions in the module?149if (SCCCount != InstrCount) {150// Yep. Emit a remark and update InstrCount.151int64_t Delta =152static_cast<int64_t>(SCCCount) - static_cast<int64_t>(InstrCount);153emitInstrCountChangedRemark(P, M, Delta, InstrCount,154FunctionToInstrCount);155InstrCount = SCCCount;156}157}158}159
160// After the CGSCCPass is done, when assertions are enabled, use161// RefreshCallGraph to verify that the callgraph was correctly updated.162#ifndef NDEBUG163if (Changed)164RefreshCallGraph(CurSCC, CG, true);165#endif166
167return Changed;168}169
170assert(PM->getPassManagerType() == PMT_FunctionPassManager &&171"Invalid CGPassManager member");172FPPassManager *FPP = (FPPassManager*)P;173
174// Run pass P on all functions in the current SCC.175for (CallGraphNode *CGN : CurSCC) {176if (Function *F = CGN->getFunction()) {177dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());178{179TimeRegion PassTimer(getPassTimer(FPP));180Changed |= FPP->runOnFunction(*F);181}182F->getContext().yield();183}184}185
186// The function pass(es) modified the IR, they may have clobbered the187// callgraph.188if (Changed && CallGraphUpToDate) {189LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Pass Dirtied SCC: " << P->getPassName()190<< '\n');191CallGraphUpToDate = false;192}193return Changed;194}
195
196/// Scan the functions in the specified CFG and resync the
197/// callgraph with the call sites found in it. This is used after
198/// FunctionPasses have potentially munged the callgraph, and can be used after
199/// CallGraphSCC passes to verify that they correctly updated the callgraph.
200///
201/// This function returns true if it devirtualized an existing function call,
202/// meaning it turned an indirect call into a direct call. This happens when
203/// a function pass like GVN optimizes away stuff feeding the indirect call.
204/// This never happens in checking mode.
205bool CGPassManager::RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG,206bool CheckingMode) {207DenseMap<Value *, CallGraphNode *> Calls;208
209LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()210<< " nodes:\n";211for (CallGraphNode *CGN212: CurSCC) CGN->dump(););213
214bool MadeChange = false;215bool DevirtualizedCall = false;216
217// Scan all functions in the SCC.218unsigned FunctionNo = 0;219for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end();220SCCIdx != E; ++SCCIdx, ++FunctionNo) {221CallGraphNode *CGN = *SCCIdx;222Function *F = CGN->getFunction();223if (!F || F->isDeclaration()) continue;224
225// Walk the function body looking for call sites. Sync up the call sites in226// CGN with those actually in the function.227
228// Keep track of the number of direct and indirect calls that were229// invalidated and removed.230unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0;231
232CallGraphNode::iterator CGNEnd = CGN->end();233
234auto RemoveAndCheckForDone = [&](CallGraphNode::iterator I) {235// Just remove the edge from the set of callees, keep track of whether236// I points to the last element of the vector.237bool WasLast = I + 1 == CGNEnd;238CGN->removeCallEdge(I);239
240// If I pointed to the last element of the vector, we have to bail out:241// iterator checking rejects comparisons of the resultant pointer with242// end.243if (WasLast)244return true;245
246CGNEnd = CGN->end();247return false;248};249
250// Get the set of call sites currently in the function.251for (CallGraphNode::iterator I = CGN->begin(); I != CGNEnd;) {252// Delete "reference" call records that do not have call instruction. We253// reinsert them as needed later. However, keep them in checking mode.254if (!I->first) {255if (CheckingMode) {256++I;257continue;258}259if (RemoveAndCheckForDone(I))260break;261continue;262}263
264// If this call site is null, then the function pass deleted the call265// entirely and the WeakTrackingVH nulled it out.266auto *Call = dyn_cast_or_null<CallBase>(*I->first);267if (!Call ||268// If we've already seen this call site, then the FunctionPass RAUW'd269// one call with another, which resulted in two "uses" in the edge270// list of the same call.271Calls.count(Call)) {272assert(!CheckingMode &&273"CallGraphSCCPass did not update the CallGraph correctly!");274
275// If this was an indirect call site, count it.276if (!I->second->getFunction())277++NumIndirectRemoved;278else279++NumDirectRemoved;280
281if (RemoveAndCheckForDone(I))282break;283continue;284}285
286assert(!Calls.count(Call) && "Call site occurs in node multiple times");287
288if (Call) {289Function *Callee = Call->getCalledFunction();290// Ignore intrinsics because they're not really function calls.291if (!Callee || !(Callee->isIntrinsic()))292Calls.insert(std::make_pair(Call, I->second));293}294++I;295}296
297// Loop over all of the instructions in the function, getting the callsites.298// Keep track of the number of direct/indirect calls added.299unsigned NumDirectAdded = 0, NumIndirectAdded = 0;300
301for (BasicBlock &BB : *F)302for (Instruction &I : BB) {303auto *Call = dyn_cast<CallBase>(&I);304if (!Call)305continue;306Function *Callee = Call->getCalledFunction();307if (Callee && Callee->isIntrinsic())308continue;309
310// If we are not in checking mode, insert potential callback calls as311// references. This is not a requirement but helps to iterate over the312// functions in the right order.313if (!CheckingMode) {314forEachCallbackFunction(*Call, [&](Function *CB) {315CGN->addCalledFunction(nullptr, CG.getOrInsertFunction(CB));316});317}318
319// If this call site already existed in the callgraph, just verify it320// matches up to expectations and remove it from Calls.321DenseMap<Value *, CallGraphNode *>::iterator ExistingIt =322Calls.find(Call);323if (ExistingIt != Calls.end()) {324CallGraphNode *ExistingNode = ExistingIt->second;325
326// Remove from Calls since we have now seen it.327Calls.erase(ExistingIt);328
329// Verify that the callee is right.330if (ExistingNode->getFunction() == Call->getCalledFunction())331continue;332
333// If we are in checking mode, we are not allowed to actually mutate334// the callgraph. If this is a case where we can infer that the335// callgraph is less precise than it could be (e.g. an indirect call336// site could be turned direct), don't reject it in checking mode, and337// don't tweak it to be more precise.338if (CheckingMode && Call->getCalledFunction() &&339ExistingNode->getFunction() == nullptr)340continue;341
342assert(!CheckingMode &&343"CallGraphSCCPass did not update the CallGraph correctly!");344
345// If not, we either went from a direct call to indirect, indirect to346// direct, or direct to different direct.347CallGraphNode *CalleeNode;348if (Function *Callee = Call->getCalledFunction()) {349CalleeNode = CG.getOrInsertFunction(Callee);350// Keep track of whether we turned an indirect call into a direct351// one.352if (!ExistingNode->getFunction()) {353DevirtualizedCall = true;354LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Devirtualized call to '"355<< Callee->getName() << "'\n");356}357} else {358CalleeNode = CG.getCallsExternalNode();359}360
361// Update the edge target in CGN.362CGN->replaceCallEdge(*Call, *Call, CalleeNode);363MadeChange = true;364continue;365}366
367assert(!CheckingMode &&368"CallGraphSCCPass did not update the CallGraph correctly!");369
370// If the call site didn't exist in the CGN yet, add it.371CallGraphNode *CalleeNode;372if (Function *Callee = Call->getCalledFunction()) {373CalleeNode = CG.getOrInsertFunction(Callee);374++NumDirectAdded;375} else {376CalleeNode = CG.getCallsExternalNode();377++NumIndirectAdded;378}379
380CGN->addCalledFunction(Call, CalleeNode);381MadeChange = true;382}383
384// We scanned the old callgraph node, removing invalidated call sites and385// then added back newly found call sites. One thing that can happen is386// that an old indirect call site was deleted and replaced with a new direct387// call. In this case, we have devirtualized a call, and CGSCCPM would like388// to iteratively optimize the new code. Unfortunately, we don't really389// have a great way to detect when this happens. As an approximation, we390// just look at whether the number of indirect calls is reduced and the391// number of direct calls is increased. There are tons of ways to fool this392// (e.g. DCE'ing an indirect call and duplicating an unrelated block with a393// direct call) but this is close enough.394if (NumIndirectRemoved > NumIndirectAdded &&395NumDirectRemoved < NumDirectAdded)396DevirtualizedCall = true;397
398// After scanning this function, if we still have entries in callsites, then399// they are dangling pointers. WeakTrackingVH should save us for this, so400// abort if401// this happens.402assert(Calls.empty() && "Dangling pointers found in call sites map");403
404// Periodically do an explicit clear to remove tombstones when processing405// large scc's.406if ((FunctionNo & 15) == 15)407Calls.clear();408}409
410LLVM_DEBUG(if (MadeChange) {411dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n";412for (CallGraphNode *CGN : CurSCC)413CGN->dump();414if (DevirtualizedCall)415dbgs() << "CGSCCPASSMGR: Refresh devirtualized a call!\n";416} else {417dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";418});419(void)MadeChange;420
421return DevirtualizedCall;422}
423
424/// Execute the body of the entire pass manager on the specified SCC.
425/// This keeps track of whether a function pass devirtualizes
426/// any calls and returns it in DevirtualizedCall.
427bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,428bool &DevirtualizedCall) {429bool Changed = false;430
431// Keep track of whether the callgraph is known to be up-to-date or not.432// The CGSSC pass manager runs two types of passes:433// CallGraphSCC Passes and other random function passes. Because other434// random function passes are not CallGraph aware, they may clobber the435// call graph by introducing new calls or deleting other ones. This flag436// is set to false when we run a function pass so that we know to clean up437// the callgraph when we need to run a CGSCCPass again.438bool CallGraphUpToDate = true;439
440// Run all passes on current SCC.441for (unsigned PassNo = 0, e = getNumContainedPasses();442PassNo != e; ++PassNo) {443Pass *P = getContainedPass(PassNo);444
445// If we're in -debug-pass=Executions mode, construct the SCC node list,446// otherwise avoid constructing this string as it is expensive.447if (isPassDebuggingExecutionsOrMore()) {448std::string Functions;449#ifndef NDEBUG450raw_string_ostream OS(Functions);451ListSeparator LS;452for (const CallGraphNode *CGN : CurSCC) {453OS << LS;454CGN->print(OS);455}456OS.flush();457#endif458dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions);459}460dumpRequiredSet(P);461
462initializeAnalysisImpl(P);463
464#ifdef EXPENSIVE_CHECKS465uint64_t RefHash = P->structuralHash(CG.getModule());466#endif467
468// Actually run this pass on the current SCC.469bool LocalChanged =470RunPassOnSCC(P, CurSCC, CG, CallGraphUpToDate, DevirtualizedCall);471
472Changed |= LocalChanged;473
474#ifdef EXPENSIVE_CHECKS475if (!LocalChanged && (RefHash != P->structuralHash(CG.getModule()))) {476llvm::errs() << "Pass modifies its input and doesn't report it: "477<< P->getPassName() << "\n";478llvm_unreachable("Pass modifies its input and doesn't report it");479}480#endif481if (LocalChanged)482dumpPassInfo(P, MODIFICATION_MSG, ON_CG_MSG, "");483dumpPreservedSet(P);484
485verifyPreservedAnalysis(P);486if (LocalChanged)487removeNotPreservedAnalysis(P);488recordAvailableAnalysis(P);489removeDeadPasses(P, "", ON_CG_MSG);490}491
492// If the callgraph was left out of date (because the last pass run was a493// functionpass), refresh it before we move on to the next SCC.494if (!CallGraphUpToDate)495DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false);496return Changed;497}
498
499/// Execute all of the passes scheduled for execution. Keep track of
500/// whether any of the passes modifies the module, and if so, return true.
501bool CGPassManager::runOnModule(Module &M) {502CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();503bool Changed = doInitialization(CG);504
505// Walk the callgraph in bottom-up SCC order.506scc_iterator<CallGraph*> CGI = scc_begin(&CG);507
508CallGraphSCC CurSCC(CG, &CGI);509while (!CGI.isAtEnd()) {510// Copy the current SCC and increment past it so that the pass can hack511// on the SCC if it wants to without invalidating our iterator.512const std::vector<CallGraphNode *> &NodeVec = *CGI;513CurSCC.initialize(NodeVec);514++CGI;515
516// At the top level, we run all the passes in this pass manager on the517// functions in this SCC. However, we support iterative compilation in the518// case where a function pass devirtualizes a call to a function. For519// example, it is very common for a function pass (often GVN or instcombine)520// to eliminate the addressing that feeds into a call. With that improved521// information, we would like the call to be an inline candidate, infer522// mod-ref information etc.523//524// Because of this, we allow iteration up to a specified iteration count.525// This only happens in the case of a devirtualized call, so we only burn526// compile time in the case that we're making progress. We also have a hard527// iteration count limit in case there is crazy code.528unsigned Iteration = 0;529bool DevirtualizedCall = false;530do {531LLVM_DEBUG(if (Iteration) dbgs()532<< " SCCPASSMGR: Re-visiting SCC, iteration #" << Iteration533<< '\n');534DevirtualizedCall = false;535Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);536} while (Iteration++ < MaxDevirtIterations && DevirtualizedCall);537
538if (DevirtualizedCall)539LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Stopped iteration after "540<< Iteration541<< " times, due to -max-devirt-iterations\n");542
543MaxSCCIterations.updateMax(Iteration);544}545Changed |= doFinalization(CG);546return Changed;547}
548
549/// Initialize CG
550bool CGPassManager::doInitialization(CallGraph &CG) {551bool Changed = false;552for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {553if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {554assert(PM->getPassManagerType() == PMT_FunctionPassManager &&555"Invalid CGPassManager member");556Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule());557} else {558Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG);559}560}561return Changed;562}
563
564/// Finalize CG
565bool CGPassManager::doFinalization(CallGraph &CG) {566bool Changed = false;567for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {568if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {569assert(PM->getPassManagerType() == PMT_FunctionPassManager &&570"Invalid CGPassManager member");571Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule());572} else {573Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG);574}575}576return Changed;577}
578
579//===----------------------------------------------------------------------===//
580// CallGraphSCC Implementation
581//===----------------------------------------------------------------------===//
582
583/// This informs the SCC and the pass manager that the specified
584/// Old node has been deleted, and New is to be used in its place.
585void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) {586assert(Old != New && "Should not replace node with self");587for (unsigned i = 0; ; ++i) {588assert(i != Nodes.size() && "Node not in SCC");589if (Nodes[i] != Old) continue;590if (New)591Nodes[i] = New;592else593Nodes.erase(Nodes.begin() + i);594break;595}596
597// Update the active scc_iterator so that it doesn't contain dangling598// pointers to the old CallGraphNode.599scc_iterator<CallGraph*> *CGI = (scc_iterator<CallGraph*>*)Context;600CGI->ReplaceNode(Old, New);601}
602
603void CallGraphSCC::DeleteNode(CallGraphNode *Old) {604ReplaceNode(Old, /*New=*/nullptr);605}
606
607//===----------------------------------------------------------------------===//
608// CallGraphSCCPass Implementation
609//===----------------------------------------------------------------------===//
610
611/// Assign pass manager to manage this pass.
612void CallGraphSCCPass::assignPassManager(PMStack &PMS,613PassManagerType PreferredType) {614// Find CGPassManager615while (!PMS.empty() &&616PMS.top()->getPassManagerType() > PMT_CallGraphPassManager)617PMS.pop();618
619assert(!PMS.empty() && "Unable to handle Call Graph Pass");620CGPassManager *CGP;621
622if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager)623CGP = (CGPassManager*)PMS.top();624else {625// Create new Call Graph SCC Pass Manager if it does not exist.626assert(!PMS.empty() && "Unable to create Call Graph Pass Manager");627PMDataManager *PMD = PMS.top();628
629// [1] Create new Call Graph Pass Manager630CGP = new CGPassManager();631
632// [2] Set up new manager's top level manager633PMTopLevelManager *TPM = PMD->getTopLevelManager();634TPM->addIndirectPassManager(CGP);635
636// [3] Assign manager to manage this new manager. This may create637// and push new managers into PMS638Pass *P = CGP;639TPM->schedulePass(P);640
641// [4] Push new manager into PMS642PMS.push(CGP);643}644
645CGP->add(this);646}
647
648/// For this class, we declare that we require and preserve the call graph.
649/// If the derived class implements this method, it should
650/// always explicitly call the implementation here.
651void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const {652AU.addRequired<CallGraphWrapperPass>();653AU.addPreserved<CallGraphWrapperPass>();654}
655
656//===----------------------------------------------------------------------===//
657// PrintCallGraphPass Implementation
658//===----------------------------------------------------------------------===//
659
660namespace {661
662/// PrintCallGraphPass - Print a Module corresponding to a call graph.663///664class PrintCallGraphPass : public CallGraphSCCPass {665std::string Banner;666raw_ostream &OS; // raw_ostream to print on.667
668public:669static char ID;670
671PrintCallGraphPass(const std::string &B, raw_ostream &OS)672: CallGraphSCCPass(ID), Banner(B), OS(OS) {}673
674void getAnalysisUsage(AnalysisUsage &AU) const override {675AU.setPreservesAll();676}677
678bool runOnSCC(CallGraphSCC &SCC) override {679bool BannerPrinted = false;680auto PrintBannerOnce = [&]() {681if (BannerPrinted)682return;683OS << Banner;684BannerPrinted = true;685};686
687bool NeedModule = llvm::forcePrintModuleIR();688if (isFunctionInPrintList("*") && NeedModule) {689PrintBannerOnce();690OS << "\n";691SCC.getCallGraph().getModule().print(OS, nullptr);692return false;693}694bool FoundFunction = false;695for (CallGraphNode *CGN : SCC) {696if (Function *F = CGN->getFunction()) {697if (!F->isDeclaration() && isFunctionInPrintList(F->getName())) {698FoundFunction = true;699if (!NeedModule) {700PrintBannerOnce();701F->print(OS);702}703}704} else if (isFunctionInPrintList("*")) {705PrintBannerOnce();706OS << "\nPrinting <null> Function\n";707}708}709if (NeedModule && FoundFunction) {710PrintBannerOnce();711OS << "\n";712SCC.getCallGraph().getModule().print(OS, nullptr);713}714return false;715}716
717StringRef getPassName() const override { return "Print CallGraph IR"; }718};719
720} // end anonymous namespace.721
722char PrintCallGraphPass::ID = 0;723
724Pass *CallGraphSCCPass::createPrinterPass(raw_ostream &OS,725const std::string &Banner) const {726return new PrintCallGraphPass(Banner, OS);727}
728
729static std::string getDescription(const CallGraphSCC &SCC) {730std::string Desc = "SCC (";731ListSeparator LS;732for (CallGraphNode *CGN : SCC) {733Desc += LS;734Function *F = CGN->getFunction();735if (F)736Desc += F->getName();737else738Desc += "<<null function>>";739}740Desc += ")";741return Desc;742}
743
744bool CallGraphSCCPass::skipSCC(CallGraphSCC &SCC) const {745OptPassGate &Gate =746SCC.getCallGraph().getModule().getContext().getOptPassGate();747return Gate.isEnabled() &&748!Gate.shouldRunPass(this->getPassName(), getDescription(SCC));749}
750
751char DummyCGSCCPass::ID = 0;752
753INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false,754false)755