17d523365SDimitry Andric //===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric // The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric //
107d523365SDimitry Andric // This file implements the CallGraphSCCPass class, which is used for passes
117d523365SDimitry Andric // which are implemented as bottom-up traversals on the call graph. Because
127d523365SDimitry Andric // there may be cycles in the call graph, passes of this type operate on the
137d523365SDimitry Andric // call-graph in SCC order: that is, they process function bottom-up, except for
147d523365SDimitry Andric // recursive functions, which they process all at once.
157d523365SDimitry Andric //
167d523365SDimitry Andric //===----------------------------------------------------------------------===//
177d523365SDimitry Andric
187d523365SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h"
192cab237bSDimitry Andric #include "llvm/ADT/DenseMap.h"
207d523365SDimitry Andric #include "llvm/ADT/SCCIterator.h"
217d523365SDimitry Andric #include "llvm/ADT/Statistic.h"
227d523365SDimitry Andric #include "llvm/Analysis/CallGraph.h"
232cab237bSDimitry Andric #include "llvm/IR/CallSite.h"
247d523365SDimitry Andric #include "llvm/IR/Function.h"
25*b5893f02SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
262cab237bSDimitry Andric #include "llvm/IR/Intrinsics.h"
277d523365SDimitry Andric #include "llvm/IR/LLVMContext.h"
287d523365SDimitry Andric #include "llvm/IR/LegacyPassManagers.h"
292cab237bSDimitry Andric #include "llvm/IR/Module.h"
303ca95b02SDimitry Andric #include "llvm/IR/OptBisect.h"
31*b5893f02SDimitry Andric #include "llvm/IR/PassTimingInfo.h"
322cab237bSDimitry Andric #include "llvm/Pass.h"
337d523365SDimitry Andric #include "llvm/Support/CommandLine.h"
347d523365SDimitry Andric #include "llvm/Support/Debug.h"
357d523365SDimitry Andric #include "llvm/Support/Timer.h"
367d523365SDimitry Andric #include "llvm/Support/raw_ostream.h"
372cab237bSDimitry Andric #include <cassert>
382cab237bSDimitry Andric #include <string>
392cab237bSDimitry Andric #include <utility>
402cab237bSDimitry Andric #include <vector>
412cab237bSDimitry Andric
427d523365SDimitry Andric using namespace llvm;
437d523365SDimitry Andric
447d523365SDimitry Andric #define DEBUG_TYPE "cgscc-passmgr"
457d523365SDimitry Andric
467d523365SDimitry Andric static cl::opt<unsigned>
477d523365SDimitry Andric MaxIterations("max-cg-scc-iterations", cl::ReallyHidden, cl::init(4));
487d523365SDimitry Andric
497d523365SDimitry Andric STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC");
507d523365SDimitry Andric
517d523365SDimitry Andric //===----------------------------------------------------------------------===//
527d523365SDimitry Andric // CGPassManager
537d523365SDimitry Andric //
547d523365SDimitry Andric /// CGPassManager manages FPPassManagers and CallGraphSCCPasses.
557d523365SDimitry Andric
567d523365SDimitry Andric namespace {
577d523365SDimitry Andric
587d523365SDimitry Andric class CGPassManager : public ModulePass, public PMDataManager {
597d523365SDimitry Andric public:
607d523365SDimitry Andric static char ID;
612cab237bSDimitry Andric
CGPassManager()622cab237bSDimitry Andric explicit CGPassManager() : ModulePass(ID), PMDataManager() {}
637d523365SDimitry Andric
647d523365SDimitry Andric /// Execute all of the passes scheduled for execution. Keep track of
657d523365SDimitry Andric /// whether any of the passes modifies the module, and if so, return true.
667d523365SDimitry Andric bool runOnModule(Module &M) override;
677d523365SDimitry Andric
687d523365SDimitry Andric using ModulePass::doInitialization;
697d523365SDimitry Andric using ModulePass::doFinalization;
707d523365SDimitry Andric
717d523365SDimitry Andric bool doInitialization(CallGraph &CG);
727d523365SDimitry Andric bool doFinalization(CallGraph &CG);
737d523365SDimitry Andric
747d523365SDimitry Andric /// Pass Manager itself does not invalidate any analysis info.
getAnalysisUsage(AnalysisUsage & Info) const757d523365SDimitry Andric void getAnalysisUsage(AnalysisUsage &Info) const override {
767d523365SDimitry Andric // CGPassManager walks SCC and it needs CallGraph.
777d523365SDimitry Andric Info.addRequired<CallGraphWrapperPass>();
787d523365SDimitry Andric Info.setPreservesAll();
797d523365SDimitry Andric }
807d523365SDimitry Andric
getPassName() const81d88c1a5aSDimitry Andric StringRef getPassName() const override { return "CallGraph Pass Manager"; }
827d523365SDimitry Andric
getAsPMDataManager()837d523365SDimitry Andric PMDataManager *getAsPMDataManager() override { return this; }
getAsPass()847d523365SDimitry Andric Pass *getAsPass() override { return this; }
857d523365SDimitry Andric
867d523365SDimitry Andric // Print passes managed by this manager
dumpPassStructure(unsigned Offset)877d523365SDimitry Andric void dumpPassStructure(unsigned Offset) override {
887d523365SDimitry Andric errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n";
897d523365SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
907d523365SDimitry Andric Pass *P = getContainedPass(Index);
917d523365SDimitry Andric P->dumpPassStructure(Offset + 1);
927d523365SDimitry Andric dumpLastUses(P, Offset+1);
937d523365SDimitry Andric }
947d523365SDimitry Andric }
957d523365SDimitry Andric
getContainedPass(unsigned N)967d523365SDimitry Andric Pass *getContainedPass(unsigned N) {
977d523365SDimitry Andric assert(N < PassVector.size() && "Pass number out of range!");
987d523365SDimitry Andric return static_cast<Pass *>(PassVector[N]);
997d523365SDimitry Andric }
1007d523365SDimitry Andric
getPassManagerType() const1017d523365SDimitry Andric PassManagerType getPassManagerType() const override {
1027d523365SDimitry Andric return PMT_CallGraphPassManager;
1037d523365SDimitry Andric }
1047d523365SDimitry Andric
1057d523365SDimitry Andric private:
1067d523365SDimitry Andric bool RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,
1077d523365SDimitry Andric bool &DevirtualizedCall);
1087d523365SDimitry Andric
1097d523365SDimitry Andric bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
1107d523365SDimitry Andric CallGraph &CG, bool &CallGraphUpToDate,
1117d523365SDimitry Andric bool &DevirtualizedCall);
112d88c1a5aSDimitry Andric bool RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG,
1137d523365SDimitry Andric bool IsCheckingMode);
1147d523365SDimitry Andric };
1157d523365SDimitry Andric
1167d523365SDimitry Andric } // end anonymous namespace.
1177d523365SDimitry Andric
1187d523365SDimitry Andric char CGPassManager::ID = 0;
1197d523365SDimitry Andric
RunPassOnSCC(Pass * P,CallGraphSCC & CurSCC,CallGraph & CG,bool & CallGraphUpToDate,bool & DevirtualizedCall)1207d523365SDimitry Andric bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
1217d523365SDimitry Andric CallGraph &CG, bool &CallGraphUpToDate,
1227d523365SDimitry Andric bool &DevirtualizedCall) {
1237d523365SDimitry Andric bool Changed = false;
1247d523365SDimitry Andric PMDataManager *PM = P->getAsPMDataManager();
1254ba319b5SDimitry Andric Module &M = CG.getModule();
1267d523365SDimitry Andric
1277d523365SDimitry Andric if (!PM) {
1287d523365SDimitry Andric CallGraphSCCPass *CGSP = (CallGraphSCCPass *)P;
1297d523365SDimitry Andric if (!CallGraphUpToDate) {
1307d523365SDimitry Andric DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false);
1317d523365SDimitry Andric CallGraphUpToDate = true;
1327d523365SDimitry Andric }
1337d523365SDimitry Andric
1347d523365SDimitry Andric {
135*b5893f02SDimitry Andric unsigned InstrCount, SCCCount = 0;
136*b5893f02SDimitry Andric StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount;
1374ba319b5SDimitry Andric bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
1387d523365SDimitry Andric TimeRegion PassTimer(getPassTimer(CGSP));
1394ba319b5SDimitry Andric if (EmitICRemark)
140*b5893f02SDimitry Andric InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);
1417d523365SDimitry Andric Changed = CGSP->runOnSCC(CurSCC);
1424ba319b5SDimitry Andric
143*b5893f02SDimitry Andric if (EmitICRemark) {
144*b5893f02SDimitry Andric // FIXME: Add getInstructionCount to CallGraphSCC.
145*b5893f02SDimitry Andric SCCCount = M.getInstructionCount();
146*b5893f02SDimitry Andric // Is there a difference in the number of instructions in the module?
147*b5893f02SDimitry Andric if (SCCCount != InstrCount) {
148*b5893f02SDimitry Andric // Yep. Emit a remark and update InstrCount.
149*b5893f02SDimitry Andric int64_t Delta =
150*b5893f02SDimitry Andric static_cast<int64_t>(SCCCount) - static_cast<int64_t>(InstrCount);
151*b5893f02SDimitry Andric emitInstrCountChangedRemark(P, M, Delta, InstrCount,
152*b5893f02SDimitry Andric FunctionToInstrCount);
153*b5893f02SDimitry Andric InstrCount = SCCCount;
154*b5893f02SDimitry Andric }
155*b5893f02SDimitry Andric }
1567d523365SDimitry Andric }
1577d523365SDimitry Andric
1587d523365SDimitry Andric // After the CGSCCPass is done, when assertions are enabled, use
1597d523365SDimitry Andric // RefreshCallGraph to verify that the callgraph was correctly updated.
1607d523365SDimitry Andric #ifndef NDEBUG
1617d523365SDimitry Andric if (Changed)
1627d523365SDimitry Andric RefreshCallGraph(CurSCC, CG, true);
1637d523365SDimitry Andric #endif
1647d523365SDimitry Andric
1657d523365SDimitry Andric return Changed;
1667d523365SDimitry Andric }
1677d523365SDimitry Andric
1687d523365SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
1697d523365SDimitry Andric "Invalid CGPassManager member");
1707d523365SDimitry Andric FPPassManager *FPP = (FPPassManager*)P;
1717d523365SDimitry Andric
1727d523365SDimitry Andric // Run pass P on all functions in the current SCC.
1737d523365SDimitry Andric for (CallGraphNode *CGN : CurSCC) {
1747d523365SDimitry Andric if (Function *F = CGN->getFunction()) {
1757d523365SDimitry Andric dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
1767d523365SDimitry Andric {
1777d523365SDimitry Andric TimeRegion PassTimer(getPassTimer(FPP));
1787d523365SDimitry Andric Changed |= FPP->runOnFunction(*F);
1797d523365SDimitry Andric }
1807d523365SDimitry Andric F->getContext().yield();
1817d523365SDimitry Andric }
1827d523365SDimitry Andric }
1837d523365SDimitry Andric
1847d523365SDimitry Andric // The function pass(es) modified the IR, they may have clobbered the
1857d523365SDimitry Andric // callgraph.
1867d523365SDimitry Andric if (Changed && CallGraphUpToDate) {
1874ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Pass Dirtied SCC: " << P->getPassName()
1884ba319b5SDimitry Andric << '\n');
1897d523365SDimitry Andric CallGraphUpToDate = false;
1907d523365SDimitry Andric }
1917d523365SDimitry Andric return Changed;
1927d523365SDimitry Andric }
1937d523365SDimitry Andric
1947d523365SDimitry Andric /// Scan the functions in the specified CFG and resync the
1957d523365SDimitry Andric /// callgraph with the call sites found in it. This is used after
1967d523365SDimitry Andric /// FunctionPasses have potentially munged the callgraph, and can be used after
1977d523365SDimitry Andric /// CallGraphSCC passes to verify that they correctly updated the callgraph.
1987d523365SDimitry Andric ///
1997d523365SDimitry Andric /// This function returns true if it devirtualized an existing function call,
2007d523365SDimitry Andric /// meaning it turned an indirect call into a direct call. This happens when
2017d523365SDimitry Andric /// a function pass like GVN optimizes away stuff feeding the indirect call.
2027d523365SDimitry Andric /// This never happens in checking mode.
RefreshCallGraph(const CallGraphSCC & CurSCC,CallGraph & CG,bool CheckingMode)203d88c1a5aSDimitry Andric bool CGPassManager::RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG,
204d88c1a5aSDimitry Andric bool CheckingMode) {
2057d523365SDimitry Andric DenseMap<Value*, CallGraphNode*> CallSites;
2067d523365SDimitry Andric
2074ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()
2087d523365SDimitry Andric << " nodes:\n";
2094ba319b5SDimitry Andric for (CallGraphNode *CGN
2104ba319b5SDimitry Andric : CurSCC) CGN->dump(););
2117d523365SDimitry Andric
2127d523365SDimitry Andric bool MadeChange = false;
2137d523365SDimitry Andric bool DevirtualizedCall = false;
2147d523365SDimitry Andric
2157d523365SDimitry Andric // Scan all functions in the SCC.
2167d523365SDimitry Andric unsigned FunctionNo = 0;
2177d523365SDimitry Andric for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end();
2187d523365SDimitry Andric SCCIdx != E; ++SCCIdx, ++FunctionNo) {
2197d523365SDimitry Andric CallGraphNode *CGN = *SCCIdx;
2207d523365SDimitry Andric Function *F = CGN->getFunction();
2217d523365SDimitry Andric if (!F || F->isDeclaration()) continue;
2227d523365SDimitry Andric
2237d523365SDimitry Andric // Walk the function body looking for call sites. Sync up the call sites in
2247d523365SDimitry Andric // CGN with those actually in the function.
2257d523365SDimitry Andric
2267d523365SDimitry Andric // Keep track of the number of direct and indirect calls that were
2277d523365SDimitry Andric // invalidated and removed.
2287d523365SDimitry Andric unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0;
2297d523365SDimitry Andric
2307d523365SDimitry Andric // Get the set of call sites currently in the function.
2317d523365SDimitry Andric for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) {
2327d523365SDimitry Andric // If this call site is null, then the function pass deleted the call
233f37b6182SDimitry Andric // entirely and the WeakTrackingVH nulled it out.
2347d523365SDimitry Andric if (!I->first ||
2357d523365SDimitry Andric // If we've already seen this call site, then the FunctionPass RAUW'd
2367d523365SDimitry Andric // one call with another, which resulted in two "uses" in the edge
2377d523365SDimitry Andric // list of the same call.
2387d523365SDimitry Andric CallSites.count(I->first) ||
2397d523365SDimitry Andric
2407d523365SDimitry Andric // If the call edge is not from a call or invoke, or it is a
2417d523365SDimitry Andric // instrinsic call, then the function pass RAUW'd a call with
2427d523365SDimitry Andric // another value. This can happen when constant folding happens
2437d523365SDimitry Andric // of well known functions etc.
2447d523365SDimitry Andric !CallSite(I->first) ||
2457d523365SDimitry Andric (CallSite(I->first).getCalledFunction() &&
2467d523365SDimitry Andric CallSite(I->first).getCalledFunction()->isIntrinsic() &&
2477d523365SDimitry Andric Intrinsic::isLeaf(
2487d523365SDimitry Andric CallSite(I->first).getCalledFunction()->getIntrinsicID()))) {
2497d523365SDimitry Andric assert(!CheckingMode &&
2507d523365SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!");
2517d523365SDimitry Andric
2527d523365SDimitry Andric // If this was an indirect call site, count it.
2537d523365SDimitry Andric if (!I->second->getFunction())
2547d523365SDimitry Andric ++NumIndirectRemoved;
2557d523365SDimitry Andric else
2567d523365SDimitry Andric ++NumDirectRemoved;
2577d523365SDimitry Andric
2587d523365SDimitry Andric // Just remove the edge from the set of callees, keep track of whether
2597d523365SDimitry Andric // I points to the last element of the vector.
2607d523365SDimitry Andric bool WasLast = I + 1 == E;
2617d523365SDimitry Andric CGN->removeCallEdge(I);
2627d523365SDimitry Andric
2637d523365SDimitry Andric // If I pointed to the last element of the vector, we have to bail out:
2647d523365SDimitry Andric // iterator checking rejects comparisons of the resultant pointer with
2657d523365SDimitry Andric // end.
2667d523365SDimitry Andric if (WasLast)
2677d523365SDimitry Andric break;
2687d523365SDimitry Andric E = CGN->end();
2697d523365SDimitry Andric continue;
2707d523365SDimitry Andric }
2717d523365SDimitry Andric
2727d523365SDimitry Andric assert(!CallSites.count(I->first) &&
2737d523365SDimitry Andric "Call site occurs in node multiple times");
2747d523365SDimitry Andric
2757d523365SDimitry Andric CallSite CS(I->first);
2767d523365SDimitry Andric if (CS) {
2777d523365SDimitry Andric Function *Callee = CS.getCalledFunction();
2787d523365SDimitry Andric // Ignore intrinsics because they're not really function calls.
2797d523365SDimitry Andric if (!Callee || !(Callee->isIntrinsic()))
2807d523365SDimitry Andric CallSites.insert(std::make_pair(I->first, I->second));
2817d523365SDimitry Andric }
2827d523365SDimitry Andric ++I;
2837d523365SDimitry Andric }
2847d523365SDimitry Andric
2857d523365SDimitry Andric // Loop over all of the instructions in the function, getting the callsites.
2867d523365SDimitry Andric // Keep track of the number of direct/indirect calls added.
2877d523365SDimitry Andric unsigned NumDirectAdded = 0, NumIndirectAdded = 0;
2887d523365SDimitry Andric
2893ca95b02SDimitry Andric for (BasicBlock &BB : *F)
2903ca95b02SDimitry Andric for (Instruction &I : BB) {
2913ca95b02SDimitry Andric CallSite CS(&I);
2927d523365SDimitry Andric if (!CS) continue;
2937d523365SDimitry Andric Function *Callee = CS.getCalledFunction();
2947d523365SDimitry Andric if (Callee && Callee->isIntrinsic()) continue;
2957d523365SDimitry Andric
2967d523365SDimitry Andric // If this call site already existed in the callgraph, just verify it
2977d523365SDimitry Andric // matches up to expectations and remove it from CallSites.
2987d523365SDimitry Andric DenseMap<Value*, CallGraphNode*>::iterator ExistingIt =
2997d523365SDimitry Andric CallSites.find(CS.getInstruction());
3007d523365SDimitry Andric if (ExistingIt != CallSites.end()) {
3017d523365SDimitry Andric CallGraphNode *ExistingNode = ExistingIt->second;
3027d523365SDimitry Andric
3037d523365SDimitry Andric // Remove from CallSites since we have now seen it.
3047d523365SDimitry Andric CallSites.erase(ExistingIt);
3057d523365SDimitry Andric
3067d523365SDimitry Andric // Verify that the callee is right.
3077d523365SDimitry Andric if (ExistingNode->getFunction() == CS.getCalledFunction())
3087d523365SDimitry Andric continue;
3097d523365SDimitry Andric
3107d523365SDimitry Andric // If we are in checking mode, we are not allowed to actually mutate
3117d523365SDimitry Andric // the callgraph. If this is a case where we can infer that the
3127d523365SDimitry Andric // callgraph is less precise than it could be (e.g. an indirect call
3137d523365SDimitry Andric // site could be turned direct), don't reject it in checking mode, and
3147d523365SDimitry Andric // don't tweak it to be more precise.
3157d523365SDimitry Andric if (CheckingMode && CS.getCalledFunction() &&
3167d523365SDimitry Andric ExistingNode->getFunction() == nullptr)
3177d523365SDimitry Andric continue;
3187d523365SDimitry Andric
3197d523365SDimitry Andric assert(!CheckingMode &&
3207d523365SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!");
3217d523365SDimitry Andric
3227d523365SDimitry Andric // If not, we either went from a direct call to indirect, indirect to
3237d523365SDimitry Andric // direct, or direct to different direct.
3247d523365SDimitry Andric CallGraphNode *CalleeNode;
3257d523365SDimitry Andric if (Function *Callee = CS.getCalledFunction()) {
3267d523365SDimitry Andric CalleeNode = CG.getOrInsertFunction(Callee);
3277d523365SDimitry Andric // Keep track of whether we turned an indirect call into a direct
3287d523365SDimitry Andric // one.
3297d523365SDimitry Andric if (!ExistingNode->getFunction()) {
3307d523365SDimitry Andric DevirtualizedCall = true;
3314ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Devirtualized call to '"
3327d523365SDimitry Andric << Callee->getName() << "'\n");
3337d523365SDimitry Andric }
3347d523365SDimitry Andric } else {
3357d523365SDimitry Andric CalleeNode = CG.getCallsExternalNode();
3367d523365SDimitry Andric }
3377d523365SDimitry Andric
3387d523365SDimitry Andric // Update the edge target in CGN.
3397d523365SDimitry Andric CGN->replaceCallEdge(CS, CS, CalleeNode);
3407d523365SDimitry Andric MadeChange = true;
3417d523365SDimitry Andric continue;
3427d523365SDimitry Andric }
3437d523365SDimitry Andric
3447d523365SDimitry Andric assert(!CheckingMode &&
3457d523365SDimitry Andric "CallGraphSCCPass did not update the CallGraph correctly!");
3467d523365SDimitry Andric
3477d523365SDimitry Andric // If the call site didn't exist in the CGN yet, add it.
3487d523365SDimitry Andric CallGraphNode *CalleeNode;
3497d523365SDimitry Andric if (Function *Callee = CS.getCalledFunction()) {
3507d523365SDimitry Andric CalleeNode = CG.getOrInsertFunction(Callee);
3517d523365SDimitry Andric ++NumDirectAdded;
3527d523365SDimitry Andric } else {
3537d523365SDimitry Andric CalleeNode = CG.getCallsExternalNode();
3547d523365SDimitry Andric ++NumIndirectAdded;
3557d523365SDimitry Andric }
3567d523365SDimitry Andric
3577d523365SDimitry Andric CGN->addCalledFunction(CS, CalleeNode);
3587d523365SDimitry Andric MadeChange = true;
3597d523365SDimitry Andric }
3607d523365SDimitry Andric
3617d523365SDimitry Andric // We scanned the old callgraph node, removing invalidated call sites and
3627d523365SDimitry Andric // then added back newly found call sites. One thing that can happen is
3637d523365SDimitry Andric // that an old indirect call site was deleted and replaced with a new direct
3647d523365SDimitry Andric // call. In this case, we have devirtualized a call, and CGSCCPM would like
3657d523365SDimitry Andric // to iteratively optimize the new code. Unfortunately, we don't really
3667d523365SDimitry Andric // have a great way to detect when this happens. As an approximation, we
3677d523365SDimitry Andric // just look at whether the number of indirect calls is reduced and the
3687d523365SDimitry Andric // number of direct calls is increased. There are tons of ways to fool this
3697d523365SDimitry Andric // (e.g. DCE'ing an indirect call and duplicating an unrelated block with a
3707d523365SDimitry Andric // direct call) but this is close enough.
3717d523365SDimitry Andric if (NumIndirectRemoved > NumIndirectAdded &&
3727d523365SDimitry Andric NumDirectRemoved < NumDirectAdded)
3737d523365SDimitry Andric DevirtualizedCall = true;
3747d523365SDimitry Andric
3757d523365SDimitry Andric // After scanning this function, if we still have entries in callsites, then
376f37b6182SDimitry Andric // they are dangling pointers. WeakTrackingVH should save us for this, so
377f37b6182SDimitry Andric // abort if
3787d523365SDimitry Andric // this happens.
3797d523365SDimitry Andric assert(CallSites.empty() && "Dangling pointers found in call sites map");
3807d523365SDimitry Andric
3817d523365SDimitry Andric // Periodically do an explicit clear to remove tombstones when processing
3827d523365SDimitry Andric // large scc's.
3837d523365SDimitry Andric if ((FunctionNo & 15) == 15)
3847d523365SDimitry Andric CallSites.clear();
3857d523365SDimitry Andric }
3867d523365SDimitry Andric
3874ba319b5SDimitry Andric LLVM_DEBUG(if (MadeChange) {
3887d523365SDimitry Andric dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n";
3897d523365SDimitry Andric for (CallGraphNode *CGN : CurSCC)
3907d523365SDimitry Andric CGN->dump();
3917d523365SDimitry Andric if (DevirtualizedCall)
3927d523365SDimitry Andric dbgs() << "CGSCCPASSMGR: Refresh devirtualized a call!\n";
3937d523365SDimitry Andric } else {
3947d523365SDimitry Andric dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
3954ba319b5SDimitry Andric });
3967d523365SDimitry Andric (void)MadeChange;
3977d523365SDimitry Andric
3987d523365SDimitry Andric return DevirtualizedCall;
3997d523365SDimitry Andric }
4007d523365SDimitry Andric
4017d523365SDimitry Andric /// Execute the body of the entire pass manager on the specified SCC.
4027d523365SDimitry Andric /// This keeps track of whether a function pass devirtualizes
4037d523365SDimitry Andric /// any calls and returns it in DevirtualizedCall.
RunAllPassesOnSCC(CallGraphSCC & CurSCC,CallGraph & CG,bool & DevirtualizedCall)4047d523365SDimitry Andric bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,
4057d523365SDimitry Andric bool &DevirtualizedCall) {
4067d523365SDimitry Andric bool Changed = false;
4077d523365SDimitry Andric
4087d523365SDimitry Andric // Keep track of whether the callgraph is known to be up-to-date or not.
4097d523365SDimitry Andric // The CGSSC pass manager runs two types of passes:
4107d523365SDimitry Andric // CallGraphSCC Passes and other random function passes. Because other
4117d523365SDimitry Andric // random function passes are not CallGraph aware, they may clobber the
4127d523365SDimitry Andric // call graph by introducing new calls or deleting other ones. This flag
4137d523365SDimitry Andric // is set to false when we run a function pass so that we know to clean up
4147d523365SDimitry Andric // the callgraph when we need to run a CGSCCPass again.
4157d523365SDimitry Andric bool CallGraphUpToDate = true;
4167d523365SDimitry Andric
4177d523365SDimitry Andric // Run all passes on current SCC.
4187d523365SDimitry Andric for (unsigned PassNo = 0, e = getNumContainedPasses();
4197d523365SDimitry Andric PassNo != e; ++PassNo) {
4207d523365SDimitry Andric Pass *P = getContainedPass(PassNo);
4217d523365SDimitry Andric
4227d523365SDimitry Andric // If we're in -debug-pass=Executions mode, construct the SCC node list,
4237d523365SDimitry Andric // otherwise avoid constructing this string as it is expensive.
4247d523365SDimitry Andric if (isPassDebuggingExecutionsOrMore()) {
4257d523365SDimitry Andric std::string Functions;
4267d523365SDimitry Andric #ifndef NDEBUG
4277d523365SDimitry Andric raw_string_ostream OS(Functions);
4287d523365SDimitry Andric for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
4297d523365SDimitry Andric I != E; ++I) {
4307d523365SDimitry Andric if (I != CurSCC.begin()) OS << ", ";
4317d523365SDimitry Andric (*I)->print(OS);
4327d523365SDimitry Andric }
4337d523365SDimitry Andric OS.flush();
4347d523365SDimitry Andric #endif
4357d523365SDimitry Andric dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions);
4367d523365SDimitry Andric }
4377d523365SDimitry Andric dumpRequiredSet(P);
4387d523365SDimitry Andric
4397d523365SDimitry Andric initializeAnalysisImpl(P);
4407d523365SDimitry Andric
4417d523365SDimitry Andric // Actually run this pass on the current SCC.
4427d523365SDimitry Andric Changed |= RunPassOnSCC(P, CurSCC, CG,
4437d523365SDimitry Andric CallGraphUpToDate, DevirtualizedCall);
4447d523365SDimitry Andric
4457d523365SDimitry Andric if (Changed)
4467d523365SDimitry Andric dumpPassInfo(P, MODIFICATION_MSG, ON_CG_MSG, "");
4477d523365SDimitry Andric dumpPreservedSet(P);
4487d523365SDimitry Andric
4497d523365SDimitry Andric verifyPreservedAnalysis(P);
4507d523365SDimitry Andric removeNotPreservedAnalysis(P);
4517d523365SDimitry Andric recordAvailableAnalysis(P);
4527d523365SDimitry Andric removeDeadPasses(P, "", ON_CG_MSG);
4537d523365SDimitry Andric }
4547d523365SDimitry Andric
4557d523365SDimitry Andric // If the callgraph was left out of date (because the last pass run was a
4567d523365SDimitry Andric // functionpass), refresh it before we move on to the next SCC.
4577d523365SDimitry Andric if (!CallGraphUpToDate)
4587d523365SDimitry Andric DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false);
4597d523365SDimitry Andric return Changed;
4607d523365SDimitry Andric }
4617d523365SDimitry Andric
4627d523365SDimitry Andric /// Execute all of the passes scheduled for execution. Keep track of
4637d523365SDimitry Andric /// whether any of the passes modifies the module, and if so, return true.
runOnModule(Module & M)4647d523365SDimitry Andric bool CGPassManager::runOnModule(Module &M) {
4657d523365SDimitry Andric CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
4667d523365SDimitry Andric bool Changed = doInitialization(CG);
4677d523365SDimitry Andric
4687d523365SDimitry Andric // Walk the callgraph in bottom-up SCC order.
4697d523365SDimitry Andric scc_iterator<CallGraph*> CGI = scc_begin(&CG);
4707d523365SDimitry Andric
4713ca95b02SDimitry Andric CallGraphSCC CurSCC(CG, &CGI);
4727d523365SDimitry Andric while (!CGI.isAtEnd()) {
4737d523365SDimitry Andric // Copy the current SCC and increment past it so that the pass can hack
4747d523365SDimitry Andric // on the SCC if it wants to without invalidating our iterator.
4757d523365SDimitry Andric const std::vector<CallGraphNode *> &NodeVec = *CGI;
476d88c1a5aSDimitry Andric CurSCC.initialize(NodeVec);
4777d523365SDimitry Andric ++CGI;
4787d523365SDimitry Andric
4797d523365SDimitry Andric // At the top level, we run all the passes in this pass manager on the
4807d523365SDimitry Andric // functions in this SCC. However, we support iterative compilation in the
4817d523365SDimitry Andric // case where a function pass devirtualizes a call to a function. For
4827d523365SDimitry Andric // example, it is very common for a function pass (often GVN or instcombine)
4837d523365SDimitry Andric // to eliminate the addressing that feeds into a call. With that improved
4847d523365SDimitry Andric // information, we would like the call to be an inline candidate, infer
4857d523365SDimitry Andric // mod-ref information etc.
4867d523365SDimitry Andric //
4877d523365SDimitry Andric // Because of this, we allow iteration up to a specified iteration count.
4887d523365SDimitry Andric // This only happens in the case of a devirtualized call, so we only burn
4897d523365SDimitry Andric // compile time in the case that we're making progress. We also have a hard
4907d523365SDimitry Andric // iteration count limit in case there is crazy code.
4917d523365SDimitry Andric unsigned Iteration = 0;
4927d523365SDimitry Andric bool DevirtualizedCall = false;
4937d523365SDimitry Andric do {
4944ba319b5SDimitry Andric LLVM_DEBUG(if (Iteration) dbgs()
4954ba319b5SDimitry Andric << " SCCPASSMGR: Re-visiting SCC, iteration #" << Iteration
4964ba319b5SDimitry Andric << '\n');
4977d523365SDimitry Andric DevirtualizedCall = false;
4987d523365SDimitry Andric Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);
4997d523365SDimitry Andric } while (Iteration++ < MaxIterations && DevirtualizedCall);
5007d523365SDimitry Andric
5017d523365SDimitry Andric if (DevirtualizedCall)
5024ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " CGSCCPASSMGR: Stopped iteration after "
5034ba319b5SDimitry Andric << Iteration
5047d523365SDimitry Andric << " times, due to -max-cg-scc-iterations\n");
5057d523365SDimitry Andric
506d8866befSDimitry Andric MaxSCCIterations.updateMax(Iteration);
5077d523365SDimitry Andric }
5087d523365SDimitry Andric Changed |= doFinalization(CG);
5097d523365SDimitry Andric return Changed;
5107d523365SDimitry Andric }
5117d523365SDimitry Andric
5127d523365SDimitry Andric /// Initialize CG
doInitialization(CallGraph & CG)5137d523365SDimitry Andric bool CGPassManager::doInitialization(CallGraph &CG) {
5147d523365SDimitry Andric bool Changed = false;
5157d523365SDimitry Andric for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
5167d523365SDimitry Andric if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
5177d523365SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
5187d523365SDimitry Andric "Invalid CGPassManager member");
5197d523365SDimitry Andric Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule());
5207d523365SDimitry Andric } else {
5217d523365SDimitry Andric Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG);
5227d523365SDimitry Andric }
5237d523365SDimitry Andric }
5247d523365SDimitry Andric return Changed;
5257d523365SDimitry Andric }
5267d523365SDimitry Andric
5277d523365SDimitry Andric /// Finalize CG
doFinalization(CallGraph & CG)5287d523365SDimitry Andric bool CGPassManager::doFinalization(CallGraph &CG) {
5297d523365SDimitry Andric bool Changed = false;
5307d523365SDimitry Andric for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
5317d523365SDimitry Andric if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
5327d523365SDimitry Andric assert(PM->getPassManagerType() == PMT_FunctionPassManager &&
5337d523365SDimitry Andric "Invalid CGPassManager member");
5347d523365SDimitry Andric Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule());
5357d523365SDimitry Andric } else {
5367d523365SDimitry Andric Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG);
5377d523365SDimitry Andric }
5387d523365SDimitry Andric }
5397d523365SDimitry Andric return Changed;
5407d523365SDimitry Andric }
5417d523365SDimitry Andric
5427d523365SDimitry Andric //===----------------------------------------------------------------------===//
5437d523365SDimitry Andric // CallGraphSCC Implementation
5447d523365SDimitry Andric //===----------------------------------------------------------------------===//
5457d523365SDimitry Andric
5467d523365SDimitry Andric /// This informs the SCC and the pass manager that the specified
5477d523365SDimitry Andric /// Old node has been deleted, and New is to be used in its place.
ReplaceNode(CallGraphNode * Old,CallGraphNode * New)5487d523365SDimitry Andric void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) {
5497d523365SDimitry Andric assert(Old != New && "Should not replace node with self");
5507d523365SDimitry Andric for (unsigned i = 0; ; ++i) {
5517d523365SDimitry Andric assert(i != Nodes.size() && "Node not in SCC");
5527d523365SDimitry Andric if (Nodes[i] != Old) continue;
5537d523365SDimitry Andric Nodes[i] = New;
5547d523365SDimitry Andric break;
5557d523365SDimitry Andric }
5567d523365SDimitry Andric
5577d523365SDimitry Andric // Update the active scc_iterator so that it doesn't contain dangling
5587d523365SDimitry Andric // pointers to the old CallGraphNode.
5597d523365SDimitry Andric scc_iterator<CallGraph*> *CGI = (scc_iterator<CallGraph*>*)Context;
5607d523365SDimitry Andric CGI->ReplaceNode(Old, New);
5617d523365SDimitry Andric }
5627d523365SDimitry Andric
5637d523365SDimitry Andric //===----------------------------------------------------------------------===//
5647d523365SDimitry Andric // CallGraphSCCPass Implementation
5657d523365SDimitry Andric //===----------------------------------------------------------------------===//
5667d523365SDimitry Andric
5677d523365SDimitry Andric /// Assign pass manager to manage this pass.
assignPassManager(PMStack & PMS,PassManagerType PreferredType)5687d523365SDimitry Andric void CallGraphSCCPass::assignPassManager(PMStack &PMS,
5697d523365SDimitry Andric PassManagerType PreferredType) {
5707d523365SDimitry Andric // Find CGPassManager
5717d523365SDimitry Andric while (!PMS.empty() &&
5727d523365SDimitry Andric PMS.top()->getPassManagerType() > PMT_CallGraphPassManager)
5737d523365SDimitry Andric PMS.pop();
5747d523365SDimitry Andric
5757d523365SDimitry Andric assert(!PMS.empty() && "Unable to handle Call Graph Pass");
5767d523365SDimitry Andric CGPassManager *CGP;
5777d523365SDimitry Andric
5787d523365SDimitry Andric if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager)
5797d523365SDimitry Andric CGP = (CGPassManager*)PMS.top();
5807d523365SDimitry Andric else {
5817d523365SDimitry Andric // Create new Call Graph SCC Pass Manager if it does not exist.
5827d523365SDimitry Andric assert(!PMS.empty() && "Unable to create Call Graph Pass Manager");
5837d523365SDimitry Andric PMDataManager *PMD = PMS.top();
5847d523365SDimitry Andric
5857d523365SDimitry Andric // [1] Create new Call Graph Pass Manager
5867d523365SDimitry Andric CGP = new CGPassManager();
5877d523365SDimitry Andric
5887d523365SDimitry Andric // [2] Set up new manager's top level manager
5897d523365SDimitry Andric PMTopLevelManager *TPM = PMD->getTopLevelManager();
5907d523365SDimitry Andric TPM->addIndirectPassManager(CGP);
5917d523365SDimitry Andric
5927d523365SDimitry Andric // [3] Assign manager to manage this new manager. This may create
5937d523365SDimitry Andric // and push new managers into PMS
5947d523365SDimitry Andric Pass *P = CGP;
5957d523365SDimitry Andric TPM->schedulePass(P);
5967d523365SDimitry Andric
5977d523365SDimitry Andric // [4] Push new manager into PMS
5987d523365SDimitry Andric PMS.push(CGP);
5997d523365SDimitry Andric }
6007d523365SDimitry Andric
6017d523365SDimitry Andric CGP->add(this);
6027d523365SDimitry Andric }
6037d523365SDimitry Andric
6047d523365SDimitry Andric /// For this class, we declare that we require and preserve the call graph.
6057d523365SDimitry Andric /// If the derived class implements this method, it should
6067d523365SDimitry Andric /// always explicitly call the implementation here.
getAnalysisUsage(AnalysisUsage & AU) const6077d523365SDimitry Andric void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const {
6087d523365SDimitry Andric AU.addRequired<CallGraphWrapperPass>();
6097d523365SDimitry Andric AU.addPreserved<CallGraphWrapperPass>();
6107d523365SDimitry Andric }
6117d523365SDimitry Andric
6127d523365SDimitry Andric //===----------------------------------------------------------------------===//
6137d523365SDimitry Andric // PrintCallGraphPass Implementation
6147d523365SDimitry Andric //===----------------------------------------------------------------------===//
6157d523365SDimitry Andric
6167d523365SDimitry Andric namespace {
6172cab237bSDimitry Andric
6187d523365SDimitry Andric /// PrintCallGraphPass - Print a Module corresponding to a call graph.
6197d523365SDimitry Andric ///
6207d523365SDimitry Andric class PrintCallGraphPass : public CallGraphSCCPass {
6217d523365SDimitry Andric std::string Banner;
6222cab237bSDimitry Andric raw_ostream &OS; // raw_ostream to print on.
6237d523365SDimitry Andric
6247d523365SDimitry Andric public:
6257d523365SDimitry Andric static char ID;
6262cab237bSDimitry Andric
PrintCallGraphPass(const std::string & B,raw_ostream & OS)6272cab237bSDimitry Andric PrintCallGraphPass(const std::string &B, raw_ostream &OS)
6282cab237bSDimitry Andric : CallGraphSCCPass(ID), Banner(B), OS(OS) {}
6297d523365SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const6307d523365SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
6317d523365SDimitry Andric AU.setPreservesAll();
6327d523365SDimitry Andric }
6337d523365SDimitry Andric
runOnSCC(CallGraphSCC & SCC)6347d523365SDimitry Andric bool runOnSCC(CallGraphSCC &SCC) override {
63524d58133SDimitry Andric bool BannerPrinted = false;
6367a7e6055SDimitry Andric auto PrintBannerOnce = [&]() {
6377a7e6055SDimitry Andric if (BannerPrinted)
6387a7e6055SDimitry Andric return;
6392cab237bSDimitry Andric OS << Banner;
6407a7e6055SDimitry Andric BannerPrinted = true;
6417a7e6055SDimitry Andric };
642*b5893f02SDimitry Andric
643*b5893f02SDimitry Andric bool NeedModule = llvm::forcePrintModuleIR();
644*b5893f02SDimitry Andric if (isFunctionInPrintList("*") && NeedModule) {
645*b5893f02SDimitry Andric PrintBannerOnce();
646*b5893f02SDimitry Andric OS << "\n";
647*b5893f02SDimitry Andric SCC.getCallGraph().getModule().print(OS, nullptr);
648*b5893f02SDimitry Andric return false;
649*b5893f02SDimitry Andric }
650*b5893f02SDimitry Andric bool FoundFunction = false;
6517d523365SDimitry Andric for (CallGraphNode *CGN : SCC) {
65224d58133SDimitry Andric if (Function *F = CGN->getFunction()) {
65324d58133SDimitry Andric if (!F->isDeclaration() && isFunctionInPrintList(F->getName())) {
654*b5893f02SDimitry Andric FoundFunction = true;
655*b5893f02SDimitry Andric if (!NeedModule) {
6567a7e6055SDimitry Andric PrintBannerOnce();
6572cab237bSDimitry Andric F->print(OS);
6587a7e6055SDimitry Andric }
659*b5893f02SDimitry Andric }
6602cab237bSDimitry Andric } else if (isFunctionInPrintList("*")) {
6617a7e6055SDimitry Andric PrintBannerOnce();
6622cab237bSDimitry Andric OS << "\nPrinting <null> Function\n";
6637d523365SDimitry Andric }
6647a7e6055SDimitry Andric }
665*b5893f02SDimitry Andric if (NeedModule && FoundFunction) {
666*b5893f02SDimitry Andric PrintBannerOnce();
667*b5893f02SDimitry Andric OS << "\n";
668*b5893f02SDimitry Andric SCC.getCallGraph().getModule().print(OS, nullptr);
669*b5893f02SDimitry Andric }
6707d523365SDimitry Andric return false;
6717d523365SDimitry Andric }
6727a7e6055SDimitry Andric
getPassName() const6737a7e6055SDimitry Andric StringRef getPassName() const override { return "Print CallGraph IR"; }
6747d523365SDimitry Andric };
6757d523365SDimitry Andric
6767d523365SDimitry Andric } // end anonymous namespace.
6777d523365SDimitry Andric
6787d523365SDimitry Andric char PrintCallGraphPass::ID = 0;
6797d523365SDimitry Andric
createPrinterPass(raw_ostream & OS,const std::string & Banner) const6802cab237bSDimitry Andric Pass *CallGraphSCCPass::createPrinterPass(raw_ostream &OS,
6817d523365SDimitry Andric const std::string &Banner) const {
6822cab237bSDimitry Andric return new PrintCallGraphPass(Banner, OS);
6837d523365SDimitry Andric }
6847d523365SDimitry Andric
skipSCC(CallGraphSCC & SCC) const6853ca95b02SDimitry Andric bool CallGraphSCCPass::skipSCC(CallGraphSCC &SCC) const {
6863ca95b02SDimitry Andric return !SCC.getCallGraph().getModule()
6873ca95b02SDimitry Andric .getContext()
6884ba319b5SDimitry Andric .getOptPassGate()
6893ca95b02SDimitry Andric .shouldRunPass(this, SCC);
6903ca95b02SDimitry Andric }
6913ca95b02SDimitry Andric
6923ca95b02SDimitry Andric char DummyCGSCCPass::ID = 0;
6932cab237bSDimitry Andric
6943ca95b02SDimitry Andric INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false,
6953ca95b02SDimitry Andric false)
696