21 #define DEBUG_TYPE "lcg"
27 while (!Worklist.
empty()) {
30 if (
Function *
F = dyn_cast<Function>(C)) {
41 if (!
F->isDeclaration() &&
42 CalleeIndexMap.
insert(std::make_pair(
F, Callees.size())).second) {
43 DEBUG(
dbgs() <<
" Added callable function: " <<
F->getName()
51 if (Visited.
insert(cast<Constant>(Op)).second)
57 : G(&G), F(F), DFSNumber(0), LowLink(0) {
59 <<
"' to the graph.\n");
67 for (
Value *Op :
I.operand_values())
70 Worklist.push_back(
C);
75 findCallees(Worklist, Visited, Callees, CalleeIndexMap);
78 void LazyCallGraph::Node::insertEdgeInternal(
Function &Callee) {
79 if (Node *
N = G->
lookup(Callee))
80 return insertEdgeInternal(*
N);
82 CalleeIndexMap.insert(std::make_pair(&Callee, Callees.
size()));
86 void LazyCallGraph::Node::insertEdgeInternal(Node &CalleeN) {
87 CalleeIndexMap.insert(std::make_pair(&CalleeN.getFunction(), Callees.size()));
88 Callees.push_back(&CalleeN);
91 void LazyCallGraph::Node::removeEdgeInternal(
Function &Callee) {
92 auto IndexMapI = CalleeIndexMap.find(&Callee);
93 assert(IndexMapI != CalleeIndexMap.end() &&
94 "Callee not in the callee set for this caller?");
96 Callees[IndexMapI->second] =
nullptr;
97 CalleeIndexMap.erase(IndexMapI);
104 if (!F.isDeclaration() && !F.hasLocalLinkage())
105 if (EntryIndexMap.insert(std::make_pair(&F, EntryNodes.
size())).second) {
106 DEBUG(
dbgs() <<
" Adding '" << F.getName()
107 <<
"' to entry set of the graph.\n");
115 if (GV.hasInitializer())
116 if (Visited.
insert(GV.getInitializer()).second)
119 DEBUG(
dbgs() <<
" Adding functions referenced by global initializers to the "
121 findCallees(Worklist, Visited, EntryNodes, EntryIndexMap);
123 for (
auto &Entry : EntryNodes) {
124 assert(!Entry.isNull() &&
125 "We can't have removed edges before we finish the constructor!");
127 SCCEntryNodes.push_back(F);
134 : BPA(std::move(G.BPA)), NodeMap(std::move(G.NodeMap)),
135 EntryNodes(std::move(G.EntryNodes)),
136 EntryIndexMap(std::move(G.EntryIndexMap)), SCCBPA(std::move(G.SCCBPA)),
137 SCCMap(std::move(G.SCCMap)), LeafSCCs(std::move(G.LeafSCCs)),
138 DFSStack(std::move(G.DFSStack)),
139 SCCEntryNodes(std::move(G.SCCEntryNodes)),
140 NextDFSNumber(G.NextDFSNumber) {
145 BPA = std::move(G.BPA);
146 NodeMap = std::move(G.NodeMap);
147 EntryNodes = std::move(G.EntryNodes);
148 EntryIndexMap = std::move(G.EntryIndexMap);
149 SCCBPA = std::move(G.SCCBPA);
150 SCCMap = std::move(G.SCCMap);
151 LeafSCCs = std::move(G.LeafSCCs);
152 DFSStack = std::move(G.DFSStack);
153 SCCEntryNodes = std::move(G.SCCEntryNodes);
154 NextDFSNumber = G.NextDFSNumber;
159 void LazyCallGraph::SCC::insert(Node &
N) {
160 N.DFSNumber = N.LowLink = -1;
162 G->SCCMap[&
N] =
this;
173 for (
const SCC *ParentC : AncestorC->ParentSCCs)
175 }
while (!AncestorWorklist.
empty());
182 CallerN.insertEdgeInternal(CalleeN);
184 assert(G->SCCMap.lookup(&CallerN) ==
this &&
"Caller must be in this SCC.");
185 assert(G->SCCMap.lookup(&CalleeN) ==
this &&
"Callee must be in this SCC.");
192 CallerN.insertEdgeInternal(CalleeN);
194 assert(G->SCCMap.lookup(&CallerN) ==
this &&
"Caller must be in this SCC.");
196 SCC &CalleeC = *G->SCCMap.lookup(&CalleeN);
197 assert(&CalleeC !=
this &&
"Callee must not be in this SCC.");
198 assert(CalleeC.isDescendantOf(*
this) &&
199 "Callee must be a descendant of the Caller.");
202 CalleeC.ParentSCCs.insert(
this);
208 CallerN.insertEdgeInternal(CalleeN);
210 assert(G->SCCMap.lookup(&CalleeN) ==
this &&
"Callee must be in this SCC.");
212 SCC &CallerC = *G->SCCMap.lookup(&CallerN);
213 assert(&CallerC !=
this &&
"Caller must not be in this SCC.");
214 assert(CallerC.isDescendantOf(*
this) &&
215 "Caller must be a descendant of the Callee.");
232 ConnectedSCCs.
insert(
this);
233 ConnectedSCCs.insert(&CallerC);
238 int ConnectedDepth = -1;
243 SCC &ParentSCC = *I++;
249 if (ConnectedSCCs.count(&ParentSCC)) {
250 ConnectedDepth = std::max<int>(ConnectedDepth, DFSSCCs.
size());
253 if (VisitedSCCs.
count(&ParentSCC))
267 if ((
int)DFSSCCs.
size() == ConnectedDepth) {
269 ConnectedSCCs.insert(C);
272 assert(ConnectedDepth < (
int)DFSSCCs.
size() &&
273 "Cannot have a connected depth greater than the DFS depth!");
290 unsigned NewNodeBeginIdx = Nodes.size();
291 for (
SCC *C : ConnectedSCCs) {
294 for (
SCC *ParentC : C->ParentSCCs)
295 if (!ConnectedSCCs.count(ParentC))
296 ParentSCCs.insert(ParentC);
297 C->ParentSCCs.clear();
300 for (
Node &ChildN : *N) {
301 SCC &ChildC = *G->SCCMap.lookup(&ChildN);
303 ChildC.ParentSCCs.erase(C);
310 for (
auto I = Nodes.begin() + NewNodeBeginIdx, E = Nodes.end(); I != E; ++
I)
311 for (
Node &ChildN : **I) {
312 SCC &ChildC = *G->SCCMap.lookup(&ChildN);
314 ChildC.ParentSCCs.insert(
this);
328 assert(G->SCCMap.lookup(&CallerN) ==
this &&
329 "The caller must be a member of this SCC.");
331 SCC &CalleeC = *G->SCCMap.lookup(&CalleeN);
332 assert(&CalleeC !=
this &&
333 "This API only supports the rmoval of inter-SCC edges.");
335 assert(std::find(G->LeafSCCs.begin(), G->LeafSCCs.end(),
this) ==
337 "Cannot have a leaf SCC caller with a different SCC callee.");
339 bool HasOtherCallToCalleeC =
false;
340 bool HasOtherCallOutsideSCC =
false;
341 for (
Node *N : *
this) {
342 for (
Node &OtherCalleeN : *N) {
343 SCC &OtherCalleeC = *G->SCCMap.lookup(&OtherCalleeN);
344 if (&OtherCalleeC == &CalleeC) {
345 HasOtherCallToCalleeC =
true;
348 if (&OtherCalleeC !=
this)
349 HasOtherCallOutsideSCC =
true;
351 if (HasOtherCallToCalleeC)
358 if (!HasOtherCallToCalleeC) {
359 bool Removed = CalleeC.ParentSCCs.erase(
this);
362 "Did not find the caller SCC in the callee SCC's parent list!");
366 if (CalleeC.ParentSCCs.empty())
369 <<
" edge orphaned the callee's SCC!\n");
373 if (!HasOtherCallOutsideSCC)
374 G->LeafSCCs.push_back(
this);
377 void LazyCallGraph::SCC::internalDFS(
382 N->LowLink = N->DFSNumber = 1;
383 int NextDFSNumber = 2;
385 assert(N->DFSNumber != 0 &&
"We should always assign a DFS number "
386 "before processing a node.");
392 if (
SCC *ChildSCC = G->SCCMap.lookup(&ChildN)) {
396 if (ChildSCC ==
this) {
398 while (!PendingSCCStack.
empty())
400 while (!DFSStack.empty())
401 insert(*DFSStack.pop_back_val().first);
407 ChildSCC->ParentSCCs.erase(
this);
412 if (ChildN.DFSNumber == 0) {
416 DFSStack.push_back(std::make_pair(N, I));
419 ChildN.LowLink = ChildN.DFSNumber = NextDFSNumber++;
428 assert(ChildN.LowLink != 0 &&
429 "Low-link must not be zero with a non-zero DFS number.");
430 if (ChildN.LowLink >= 0 && ChildN.LowLink < N->LowLink)
431 N->LowLink = ChildN.LowLink;
435 if (N->LowLink == N->DFSNumber) {
436 ResultSCCs.
push_back(G->formSCC(N, PendingSCCStack));
437 if (DFSStack.empty())
447 assert(!DFSStack.empty() &&
"We shouldn't have an empty stack!");
450 N = DFSStack.back().first;
451 I = DFSStack.back().second;
466 if (&CallerN == &CalleeN)
471 Worklist.
swap(Nodes);
472 for (
Node *N : Worklist) {
478 assert(Worklist.size() > 1 &&
"We have to have at least two nodes to have an "
479 "edge between them that is within the SCC.");
493 Node *N = Worklist.pop_back_val();
494 if (N->DFSNumber == 0)
495 internalDFS(DFSStack, PendingSCCStack, N, ResultSCCs);
497 assert(DFSStack.
empty() &&
"Didn't flush the entire DFS stack!");
498 assert(PendingSCCStack.
empty() &&
"Didn't flush all pending SCC nodes!");
499 }
while (!Worklist.empty());
502 bool IsLeafSCC =
true;
503 for (
Node *N : Nodes) {
504 for (
Node &ChildN : *N) {
505 SCC &ChildSCC = *G->SCCMap.lookup(&ChildN);
506 if (&ChildSCC ==
this)
508 ChildSCC.ParentSCCs.insert(
this);
513 if (!ResultSCCs.
empty())
514 assert(!IsLeafSCC &&
"This SCC cannot be a leaf as we have split out new "
515 "SCCs by removing this edge.");
516 if (!std::any_of(G->LeafSCCs.begin(), G->LeafSCCs.end(),
517 [&](
SCC *
C) {
return C ==
this; }))
518 assert(!IsLeafSCC &&
"This SCC cannot be a leaf as it already had child "
519 "SCCs before we removed this edge.");
523 if (!IsLeafSCC && !ResultSCCs.
empty())
524 G->LeafSCCs.erase(
std::remove(G->LeafSCCs.begin(), G->LeafSCCs.end(),
this),
532 assert(SCCMap.empty() && DFSStack.empty() &&
533 "This method cannot be called after SCCs have been formed!");
535 return CallerN.insertEdgeInternal(Callee);
539 assert(SCCMap.empty() && DFSStack.empty() &&
540 "This method cannot be called after SCCs have been formed!");
542 return CallerN.removeEdgeInternal(Callee);
546 return *
new (MappedN = BPA.Allocate()) Node(*
this, F);
549 void LazyCallGraph::updateGraphPtrs() {
553 for (
auto &Entry : EntryNodes)
554 if (Node *EntryN = Entry.dyn_cast<Node *>())
557 while (!Worklist.
empty()) {
560 for (
auto &Callee : N->Callees)
561 if (!Callee.isNull())
562 if (Node *CalleeN = Callee.dyn_cast<Node *>())
571 while (!Worklist.
empty()) {
574 Worklist.
insert(Worklist.
end(), C->ParentSCCs.begin(),
575 C->ParentSCCs.end());
584 SCC *NewSCC =
new (SCCBPA.Allocate()) SCC(*
this);
586 while (!NodeStack.
empty() && NodeStack.
back()->DFSNumber > RootN->DFSNumber) {
587 assert(NodeStack.
back()->LowLink >= RootN->LowLink &&
588 "We cannot have a low link in an SCC lower than its root on the "
592 NewSCC->insert(*RootN);
597 bool IsLeafSCC =
true;
598 for (Node *SCCN : NewSCC->Nodes)
599 for (Node &SCCChildN : *SCCN) {
600 SCC &ChildSCC = *SCCMap.lookup(&SCCChildN);
601 if (&ChildSCC == NewSCC)
603 ChildSCC.ParentSCCs.insert(NewSCC);
609 LeafSCCs.push_back(NewSCC);
617 if (!DFSStack.empty()) {
618 N = DFSStack.back().first;
619 I = DFSStack.back().second;
624 if (SCCEntryNodes.empty())
627 N = &
get(*SCCEntryNodes.pop_back_val());
628 }
while (N->DFSNumber != 0);
630 N->LowLink = N->DFSNumber = 1;
635 assert(N->DFSNumber != 0 &&
"We should always assign a DFS number "
636 "before placing a node onto the stack.");
641 if (ChildN.DFSNumber == 0) {
645 DFSStack.push_back(std::make_pair(N, N->begin()));
648 assert(!SCCMap.count(&ChildN) &&
649 "Found a node with 0 DFS number but already in an SCC!");
650 ChildN.LowLink = ChildN.DFSNumber = NextDFSNumber++;
658 assert(ChildN.LowLink != 0 &&
659 "Low-link must not be zero with a non-zero DFS number.");
660 if (ChildN.LowLink >= 0 && ChildN.LowLink < N->LowLink)
661 N->LowLink = ChildN.LowLink;
665 if (N->LowLink == N->DFSNumber)
667 return formSCC(N, PendingSCCStack);
676 assert(!DFSStack.empty() &&
"We never found a viable root!");
677 N = DFSStack.back().first;
678 I = DFSStack.back().second;
683 char LazyCallGraphAnalysis::PassID;
691 if (Printed.
insert(&ChildN).second)
694 OS <<
" Call edges in function: " << N.getFunction().getName() <<
"\n";
696 OS <<
" -> " << I->getFunction().getName() <<
"\n";
702 ptrdiff_t SCCSize = std::distance(SCC.
begin(), SCC.
end());
703 OS <<
" SCC with " << SCCSize <<
" functions:\n";
706 OS <<
" " << N->getFunction().getName() <<
"\n";
720 if (Printed.
insert(&N).second)
parent_iterator parent_begin() const
void push_back(const T &Elt)
A Module instance is used to store all the information related to an LLVM module. ...
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
Implements a lazy call graph analysis and related passes for the new pass manager.
void removeInterSCCEdge(Node &CallerN, Node &CalleeN)
Remove an edge whose source is in this SCC and target is not.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
bool isDescendantOf(const SCC &C) const
Test if this SCC is a descendant of C.
StringRef getName() const
Return a constant reference to the value's name.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
A lazy iterator used for both the entry nodes and child nodes.
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void insertIntraSCCEdge(Node &CallerN, Node &CalleeN)
Insert an edge from one node in this SCC to another in this SCC.
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
SmallVector< SCC *, 1 > removeIntraSCCEdge(Node &CallerN, Node &CalleeN)
Remove an edge which is entirely within this SCC.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
A lazily constructed view of the call graph of a module.
void insertEdge(Node &Caller, Function &Callee)
Update the call graph after inserting a new edge.
LazyCallGraph & operator=(LazyCallGraph &&RHS)
void insertOutgoingEdge(Node &CallerN, Node &CalleeN)
Insert an edge whose tail is in this SCC and head is in some child SCC.
static void printSCC(raw_ostream &OS, LazyCallGraph::SCC &SCC)
void removeEdge(Node &Caller, Function &Callee)
Update the call graph after deleting an edge.
An abstract set of preserved analyses following a transformation pass run.
LLVM Basic Block Representation.
void swap(SmallVectorImpl &RHS)
This is an important base class in LLVM.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM)
SmallVector< SCC *, 1 > insertIncomingEdge(Node &CallerN, Node &CalleeN)
Insert an edge whose tail is in a descendant SCC and head is in this SCC.
A node in the call graph.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Function & getFunction() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
static void printNodes(raw_ostream &OS, LazyCallGraph::Node &N, SmallPtrSetImpl< LazyCallGraph::Node * > &Printed)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
An iterator type that allows iterating over the pointees via some other iterator. ...
PassT::Result & getResult(IRUnitT &IR)
Get the result of an analysis pass for this module.
LazyCallGraph::iterator iterator
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
parent_iterator parent_end() const
iterator insert(iterator I, T &&Elt)
LazyCallGraphPrinterPass(raw_ostream &OS)
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
static void findCallees(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, SmallVectorImpl< PointerUnion< Function *, LazyCallGraph::Node * >> &Callees, DenseMap< Function *, size_t > &CalleeIndexMap)
iterator_range< value_op_iterator > operand_values()
An analysis pass which computes the call graph for a module.
bool isChildOf(const SCC &C) const
Test if this SCC is a child of C.
LLVM Value Representation.
An SCC of the call graph.
This class implements an extremely fast bulk output stream that can only output to a stream...
C - The default llvm calling convention, compatible with C.
A generic analysis pass manager with lazy running and caching of results.
This header defines various interfaces for pass management in LLVM.
LazyCallGraph(Module &M)
Construct a graph for the given module.
PointerUnion - This implements a discriminated union of two pointer types, and keeps the discriminato...