44 #define DEBUG_TYPE "cgscc-passmgr" 49 STATISTIC(MaxSCCIterations,
"Maximum CGSCCPassMgr iterations on one SCC");
66 bool runOnModule(
Module &M)
override;
81 StringRef getPassName()
const override {
return "CallGraph Pass Manager"; }
84 Pass *getAsPass()
override {
return this; }
87 void dumpPassStructure(
unsigned Offset)
override {
88 errs().
indent(Offset*2) <<
"Call Graph SCC Pass Manager\n";
92 dumpLastUses(P, Offset+1);
96 Pass *getContainedPass(
unsigned N) {
97 assert(N < PassVector.size() &&
"Pass number out of range!");
98 return static_cast<Pass *
>(PassVector[
N]);
107 bool &DevirtualizedCall);
111 bool &DevirtualizedCall);
113 bool IsCheckingMode);
122 bool &DevirtualizedCall) {
123 bool Changed =
false;
129 if (!CallGraphUpToDate) {
130 DevirtualizedCall |= RefreshCallGraph(CurSCC, CG,
false);
131 CallGraphUpToDate =
true;
140 InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);
147 if (SCCCount != InstrCount) {
150 static_cast<int64_t
>(SCCCount) - static_cast<int64_t>(InstrCount);
151 emitInstrCountChangedRemark(P, M, Delta, InstrCount,
152 FunctionToInstrCount);
153 InstrCount = SCCCount;
162 RefreshCallGraph(CurSCC, CG,
true);
169 "Invalid CGPassManager member");
178 Changed |= FPP->runOnFunction(*
F);
180 F->getContext().yield();
186 if (Changed && CallGraphUpToDate) {
189 CallGraphUpToDate =
false;
210 : CurSCC) CGN->dump(););
212 bool MadeChange =
false;
213 bool DevirtualizedCall =
false;
216 unsigned FunctionNo = 0;
218 SCCIdx !=
E; ++SCCIdx, ++FunctionNo) {
228 unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0;
238 CallSites.
count(
I->first) ||
250 "CallGraphSCCPass did not update the CallGraph correctly!");
253 if (!
I->second->getFunction())
254 ++NumIndirectRemoved;
260 bool WasLast =
I + 1 ==
E;
273 "Call site occurs in node multiple times");
280 CallSites.
insert(std::make_pair(
I->first,
I->second));
287 unsigned NumDirectAdded = 0, NumIndirectAdded = 0;
293 Function *Callee = CS.getCalledFunction();
299 CallSites.
find(CS.getInstruction());
300 if (ExistingIt != CallSites.
end()) {
304 CallSites.
erase(ExistingIt);
307 if (ExistingNode->
getFunction() == CS.getCalledFunction())
315 if (CheckingMode && CS.getCalledFunction() &&
320 "CallGraphSCCPass did not update the CallGraph correctly!");
325 if (
Function *Callee = CS.getCalledFunction()) {
330 DevirtualizedCall =
true;
332 << Callee->
getName() <<
"'\n");
345 "CallGraphSCCPass did not update the CallGraph correctly!");
349 if (
Function *Callee = CS.getCalledFunction()) {
371 if (NumIndirectRemoved > NumIndirectAdded &&
372 NumDirectRemoved < NumDirectAdded)
373 DevirtualizedCall =
true;
379 assert(CallSites.
empty() &&
"Dangling pointers found in call sites map");
383 if ((FunctionNo & 15) == 15)
388 dbgs() <<
"CGSCCPASSMGR: Refreshed SCC is now:\n";
391 if (DevirtualizedCall)
392 dbgs() <<
"CGSCCPASSMGR: Refresh devirtualized a call!\n";
394 dbgs() <<
"CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
398 return DevirtualizedCall;
405 bool &DevirtualizedCall) {
406 bool Changed =
false;
415 bool CallGraphUpToDate =
true;
418 for (
unsigned PassNo = 0, e = getNumContainedPasses();
419 PassNo != e; ++PassNo) {
420 Pass *P = getContainedPass(PassNo);
424 if (isPassDebuggingExecutionsOrMore()) {
425 std::string Functions;
430 if (
I != CurSCC.
begin()) OS <<
", ";
439 initializeAnalysisImpl(P);
442 Changed |= RunPassOnSCC(P, CurSCC, CG,
443 CallGraphUpToDate, DevirtualizedCall);
449 verifyPreservedAnalysis(P);
450 removeNotPreservedAnalysis(P);
451 recordAvailableAnalysis(P);
457 if (!CallGraphUpToDate)
458 DevirtualizedCall |= RefreshCallGraph(CurSCC, CG,
false);
464 bool CGPassManager::runOnModule(
Module &M) {
465 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
466 bool Changed = doInitialization(CG);
475 const std::vector<CallGraphNode *> &NodeVec = *CGI;
491 unsigned Iteration = 0;
492 bool DevirtualizedCall =
false;
495 <<
" SCCPASSMGR: Re-visiting SCC, iteration #" << Iteration
497 DevirtualizedCall =
false;
498 Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);
501 if (DevirtualizedCall)
504 <<
" times, due to -max-cg-scc-iterations\n");
506 MaxSCCIterations.updateMax(Iteration);
508 Changed |= doFinalization(CG);
513 bool CGPassManager::doInitialization(
CallGraph &CG) {
514 bool Changed =
false;
515 for (
unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
516 if (
PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
518 "Invalid CGPassManager member");
528 bool CGPassManager::doFinalization(
CallGraph &CG) {
529 bool Changed =
false;
530 for (
unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) {
531 if (
PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) {
533 "Invalid CGPassManager member");
549 assert(Old != New &&
"Should not replace node with self");
550 for (
unsigned i = 0; ; ++i) {
551 assert(i != Nodes.size() &&
"Node not in SCC");
552 if (Nodes[i] != Old)
continue;
571 while (!PMS.
empty() &&
575 assert(!PMS.
empty() &&
"Unable to handle Call Graph Pass");
579 CGP = (CGPassManager*)PMS.
top();
582 assert(!PMS.
empty() &&
"Unable to create Call Graph Pass Manager");
586 CGP =
new CGPassManager();
627 PrintCallGraphPass(
const std::string &
B,
raw_ostream &OS)
635 bool BannerPrinted =
false;
636 auto PrintBannerOnce = [&]() {
640 BannerPrinted =
true;
650 bool FoundFunction =
false;
654 FoundFunction =
true;
662 OS <<
"\nPrinting <null> Function\n";
665 if (NeedModule && FoundFunction) {
668 SCC.getCallGraph().getModule().print(OS,
nullptr);
673 StringRef getPassName()
const override {
return "Print CallGraph IR"; }
681 const std::string &Banner)
const {
682 return new PrintCallGraphPass(Banner, OS);
Pass interface - Implemented by all 'passes'.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
PassManagerType
Different types of internal pass managers.
bool forcePrintModuleIR()
forcePrintModuleIR - returns true if IR printing passes should
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
This class represents lattice values for constants.
virtual PMDataManager * getAsPMDataManager()
virtual void dumpPassStructure(unsigned Offset=0)
A Module instance is used to store all the information related to an LLVM module. ...
void ReplaceNode(NodeRef Old, NodeRef New)
This informs the scc_iterator that the specified Old node has been deleted, and New is to be used in ...
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
STATISTIC(NumFunctions, "Total number of functions")
static unsigned InstrCount
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
A node in the call graph for a module.
bool skipSCC(CallGraphSCC &SCC) const
Optional passes call this function to check whether the pass should be skipped.
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph...
Module & getModule() const
Returns the module the call graph corresponds to.
Pass * createPrinterPass(raw_ostream &OS, const std::string &Banner) const override
createPrinterPass - Get a pass that prints the Module corresponding to a CallGraph.
PMTopLevelManager manages LastUser info and collects common APIs used by top level pass managers...
Timer * getPassTimer(Pass *)
Request the timer for this legacy-pass-manager's pass instance.
The TimeRegion class is used as a helper class to call the startTimer() and stopTimer() methods of th...
virtual bool shouldRunPass(const Pass *P, const Module &U)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void addCalledFunction(CallSite CS, CallGraphNode *M)
Adds a function to the list of functions called by this one.
void schedulePass(Pass *P)
Schedule pass P for execution.
AnalysisUsage & addRequired()
LLVMContext & getContext() const
Get the global data context.
void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode)
Replaces the edge in the node for the specified call site with a new one.
virtual bool doFinalization(Module &)
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
unsigned getInstructionCount()
Returns the number of non-debug IR instructions in the module.
const CallGraph & getCallGraph()
This header defines classes/functions to handle pass execution timing information with interfaces for...
FPPassManager manages BBPassManagers and FunctionPasses.
PMStack - This class implements a stack data structure of PMDataManager pointers. ...
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
void dump() const
Print out this call graph node.
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time...
amdgpu Simplify well known AMD library false Value * Callee
Analysis containing CSE Info
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
static cl::opt< unsigned > MaxIterations("max-cg-scc-iterations", cl::ReallyHidden, cl::init(4))
iterator find(const_arg_type_t< KeyT > Val)
initializer< Ty > init(const Ty &Val)
bool erase(const KeyT &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This pass is required by interprocedural register allocation.
The ModulePass which wraps up a CallGraph and the logic to build it.
bool isLeaf(ID id)
Returns true if the intrinsic is a leaf, i.e.
CallGraphNode * getCallsExternalNode() const
LLVM Basic Block Representation.
bool shouldEmitInstrCountChangedRemark()
Return true if size-info optimization remark is enabled, false otherwise.
void addIndirectPassManager(PMDataManager *Manager)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
virtual PassManagerType getPassManagerType() const
Represent the analysis usage information of a pass.
void initialize(ArrayRef< CallGraphNode *> NewNodes)
void assignPassManager(PMStack &PMS, PassManagerType PMT) override
Assign pass manager to manager this pass.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Function * getFunction() const
Returns the function that this call graph node represents.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the module to an output stream with an optional AssemblyAnnotationWriter.
Module.h This file contains the declarations for the Module class.
This file declares the interface for bisecting optimizations.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
bool isFunctionInPrintList(StringRef FunctionName)
isFunctionInPrintList - returns true if a function should be printed via
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
void setPreservesAll()
Set by analyses that do not transform their input at all.
void removeCallEdge(iterator I)
The basic data container for the call graph of a Module of IR.
void ReplaceNode(CallGraphNode *Old, CallGraphNode *New)
ReplaceNode - This informs the SCC and the pass manager that the specified Old node has been deleted...
StringRef getName() const
Return a constant reference to the value's name.
std::vector< CallGraphNode * >::const_iterator iterator
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
std::vector< CallRecord >::iterator iterator
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
void push(PMDataManager *PM)
LLVM_NODISCARD bool empty() const
PMDataManager provides the common place to manage the analysis data used by pass managers.
This file defines passes to print out IR in various granularities.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
FunTy * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
virtual bool runOnSCC(CallGraphSCC &SCC)=0
runOnSCC - This method should be implemented by the subclass to perform whatever action is necessary ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
PMDataManager * top() const
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
CallGraphNode * getOrInsertFunction(const Function *F)
Similar to operator[], but this will insert a new CallGraphNode for F if one does not already exist...
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.