33 #define DEBUG_TYPE "cgscc-passmgr"
38 STATISTIC(MaxSCCIterations,
"Maximum CGSCCPassMgr iterations on one SCC");
50 explicit CGPassManager()
55 bool runOnModule(
Module &M)
override;
70 StringRef getPassName()
const override {
return "CallGraph Pass Manager"; }
73 Pass *getAsPass()
override {
return this; }
76 void dumpPassStructure(
unsigned Offset)
override {
77 errs().
indent(Offset*2) <<
"Call Graph SCC Pass Manager\n";
78 for (
unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
79 Pass *
P = getContainedPass(Index);
81 dumpLastUses(P, Offset+1);
85 Pass *getContainedPass(
unsigned N) {
86 assert(N < PassVector.size() &&
"Pass number out of range!");
87 return static_cast<Pass *
>(PassVector[
N]);
96 bool &DevirtualizedCall);
100 bool &DevirtualizedCall);
102 bool IsCheckingMode);
112 bool &DevirtualizedCall) {
113 bool Changed =
false;
118 if (!CallGraphUpToDate) {
119 DevirtualizedCall |= RefreshCallGraph(CurSCC, CG,
false);
120 CallGraphUpToDate =
true;
132 RefreshCallGraph(CurSCC, CG,
true);
140 "Invalid CGPassManager member");
149 Changed |= FPP->runOnFunction(*
F);
151 F->getContext().yield();
157 if (Changed && CallGraphUpToDate) {
158 DEBUG(
dbgs() <<
"CGSCCPASSMGR: Pass Dirtied SCC: "
160 CallGraphUpToDate =
false;
180 DEBUG(
dbgs() <<
"CGSCCPASSMGR: Refreshing SCC with " << CurSCC.
size()
186 bool MadeChange =
false;
187 bool DevirtualizedCall =
false;
190 unsigned FunctionNo = 0;
192 SCCIdx !=
E; ++SCCIdx, ++FunctionNo) {
202 unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0;
212 CallSites.
count(
I->first) ||
224 "CallGraphSCCPass did not update the CallGraph correctly!");
227 if (!
I->second->getFunction())
228 ++NumIndirectRemoved;
234 bool WasLast =
I + 1 ==
E;
247 "Call site occurs in node multiple times");
254 CallSites.
insert(std::make_pair(
I->first,
I->second));
261 unsigned NumDirectAdded = 0, NumIndirectAdded = 0;
273 CallSites.
find(
CS.getInstruction());
274 if (ExistingIt != CallSites.
end()) {
278 CallSites.
erase(ExistingIt);
289 if (CheckingMode &&
CS.getCalledFunction() &&
294 "CallGraphSCCPass did not update the CallGraph correctly!");
299 if (
Function *Callee =
CS.getCalledFunction()) {
304 DevirtualizedCall =
true;
305 DEBUG(
dbgs() <<
" CGSCCPASSMGR: Devirtualized call to '"
306 << Callee->
getName() <<
"'\n");
319 "CallGraphSCCPass did not update the CallGraph correctly!");
323 if (
Function *Callee =
CS.getCalledFunction()) {
345 if (NumIndirectRemoved > NumIndirectAdded &&
346 NumDirectRemoved < NumDirectAdded)
347 DevirtualizedCall =
true;
352 assert(CallSites.
empty() &&
"Dangling pointers found in call sites map");
356 if ((FunctionNo & 15) == 15)
360 DEBUG(
if (MadeChange) {
361 dbgs() <<
"CGSCCPASSMGR: Refreshed SCC is now:\n";
364 if (DevirtualizedCall)
365 dbgs() <<
"CGSCCPASSMGR: Refresh devirtualized a call!\n";
368 dbgs() <<
"CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
373 return DevirtualizedCall;
380 bool &DevirtualizedCall) {
381 bool Changed =
false;
390 bool CallGraphUpToDate =
true;
393 for (
unsigned PassNo = 0, e = getNumContainedPasses();
394 PassNo != e; ++PassNo) {
395 Pass *P = getContainedPass(PassNo);
399 if (isPassDebuggingExecutionsOrMore()) {
400 std::string Functions;
405 if (
I != CurSCC.
begin()) OS <<
", ";
414 initializeAnalysisImpl(P);
417 Changed |= RunPassOnSCC(P, CurSCC, CG,
418 CallGraphUpToDate, DevirtualizedCall);
424 verifyPreservedAnalysis(P);
425 removeNotPreservedAnalysis(P);
426 recordAvailableAnalysis(P);
432 if (!CallGraphUpToDate)
433 DevirtualizedCall |= RefreshCallGraph(CurSCC, CG,
false);
439 bool CGPassManager::runOnModule(
Module &M) {
440 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
441 bool Changed = doInitialization(CG);
450 const std::vector<CallGraphNode *> &NodeVec = *CGI;
466 unsigned Iteration = 0;
467 bool DevirtualizedCall =
false;
470 dbgs() <<
" SCCPASSMGR: Re-visiting SCC, iteration #"
471 << Iteration <<
'\n');
472 DevirtualizedCall =
false;
473 Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall);
476 if (DevirtualizedCall)
477 DEBUG(
dbgs() <<
" CGSCCPASSMGR: Stopped iteration after " << Iteration
478 <<
" times, due to -max-cg-scc-iterations\n");
480 if (Iteration > MaxSCCIterations)
481 MaxSCCIterations = Iteration;
484 Changed |= doFinalization(CG);
490 bool CGPassManager::doInitialization(
CallGraph &CG) {
491 bool Changed =
false;
492 for (
unsigned i = 0, e = getNumContainedPasses();
i != e; ++
i) {
493 if (
PMDataManager *PM = getContainedPass(
i)->getAsPMDataManager()) {
495 "Invalid CGPassManager member");
505 bool CGPassManager::doFinalization(
CallGraph &CG) {
506 bool Changed =
false;
507 for (
unsigned i = 0, e = getNumContainedPasses();
i != e; ++
i) {
508 if (
PMDataManager *PM = getContainedPass(
i)->getAsPMDataManager()) {
510 "Invalid CGPassManager member");
526 assert(Old != New &&
"Should not replace node with self");
527 for (
unsigned i = 0; ; ++
i) {
528 assert(
i != Nodes.size() &&
"Node not in SCC");
529 if (Nodes[
i] != Old)
continue;
549 while (!PMS.
empty() &&
553 assert(!PMS.
empty() &&
"Unable to handle Call Graph Pass");
557 CGP = (CGPassManager*)PMS.
top();
560 assert(!PMS.
empty() &&
"Unable to create Call Graph Pass Manager");
564 CGP =
new CGPassManager();
604 PrintCallGraphPass(
const std::string &
B,
raw_ostream &o)
618 Out <<
"\nPrinting <null> Function\n";
629 const std::string &Banner)
const {
630 return new PrintCallGraphPass(Banner, O);
Pass interface - Implemented by all 'passes'.
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 shouldRunPass(const Pass *P, const UnitT &U)
Checks the bisect limit to determine if the specified pass should run.
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.
STATISTIC(NumFunctions,"Total number of functions")
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 dump() const
Print out this call graph node.
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 ...
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
void initialize(ArrayRef< CallGraphNode * > NewNodes)
A node in the call graph for a module.
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph...
std::vector< CallGraphNode * >::const_iterator iterator
virtual PassManagerType getPassManagerType() const
Module & getModule() const
Returns the module the call graph corresponds to.
PMTopLevelManager manages LastUser info and collects common APIs used by top level pass managers...
Timer * getPassTimer(Pass *)
If TimingInfo is enabled then start pass timer.
StringRef getName() const
Return a constant reference to the value's name.
Function * getFunction() const
Returns the function that this call graph node represents.
The TimeRegion class is used as a helper class to call the startTimer() and stopTimer() methods of th...
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.
std::vector< CallRecord >::iterator iterator
void schedulePass(Pass *P)
Schedule pass P for execution.
AnalysisUsage & addRequired()
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...
const CallGraph & getCallGraph()
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.
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
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))
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
initializer< Ty > init(const Ty &Val)
bool erase(const KeyT &Val)
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.
LLVM Basic Block Representation.
void addIndirectPassManager(PMDataManager *Manager)
Pass * createPrinterPass(raw_ostream &O, const std::string &Banner) const override
createPrinterPass - Get a pass that prints the Module corresponding to a CallGraph.
Represent the analysis usage information of a pass.
void assignPassManager(PMStack &PMS, PassManagerType PMT) override
Assign pass manager to manager this pass.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
PMDataManager * top() const
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...
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
OptBisect & getOptBisect()
Access the object which manages optimization bisection for failure analysis.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
iterator find(const KeyT &Val)
void push(PMDataManager *PM)
PMDataManager provides the common place to manage the analysis data used by pass managers.
LLVM_NODISCARD bool empty() const
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.
FunTy * getCalledFunction() const
getCalledFunction - Return the function being called if this is a direct call, otherwise return null ...
bool skipSCC(CallGraphSCC &SCC) const
Optional passes call this function to check whether the pass should be skipped.
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.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW=nullptr, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the function to an output stream with an optional AssemblyAnnotationWriter. ...
LLVMContext & getContext() const
Get the global data context.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
CallGraphNode * getCallsExternalNode() const