32#ifdef EXPENSIVE_CHECKS
38#define DEBUG_TYPE "lcg"
40void LazyCallGraph::EdgeSequence::insertEdgeInternal(
Node &TargetN,
42 EdgeIndexMap.try_emplace(&TargetN, Edges.
size());
46void LazyCallGraph::EdgeSequence::setEdgeKind(
Node &TargetN,
Edge::Kind EK) {
47 Edges[EdgeIndexMap.find(&TargetN)->second].setKind(EK);
50bool LazyCallGraph::EdgeSequence::removeEdgeInternal(
Node &TargetN) {
51 auto IndexMapI = EdgeIndexMap.find(&TargetN);
52 if (IndexMapI == EdgeIndexMap.end())
55 Edges[IndexMapI->second] = Edge();
56 EdgeIndexMap.erase(IndexMapI);
66 LLVM_DEBUG(
dbgs() <<
" Added callable function: " <<
N.getName() <<
"\n");
71 assert(!Edges &&
"Must not have already populated the edges for this node!");
74 <<
"' to the graph.\n");
76 Edges = EdgeSequence();
100 if (
auto *CB = dyn_cast<CallBase>(&
I))
101 if (
Function *Callee = CB->getCalledFunction())
102 if (!
Callee->isDeclaration())
103 if (Callees.
insert(Callee).second) {
105 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(*Callee),
109 for (
Value *
Op :
I.operand_values())
119 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(
F),
125 for (
auto *
F :
G->LibFunctions)
127 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(*
F),
133void LazyCallGraph::Node::replaceFunction(
Function &NewF) {
134 assert(
F != &NewF &&
"Must not replace a function with itself!");
138#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140 dbgs() << *
this <<
'\n';
156 LLVM_DEBUG(
dbgs() <<
"Building CG for module: " << M.getModuleIdentifier()
159 if (
F.isDeclaration())
165 LibFunctions.insert(&
F);
167 if (
F.hasLocalLinkage())
173 <<
"' to entry set of the graph.\n");
179 for (
auto &
A : M.aliases()) {
180 if (
A.hasLocalLinkage())
182 if (
Function*
F = dyn_cast<Function>(
A.getAliasee())) {
184 <<
"' with alias '" <<
A.getName()
185 <<
"' to entry set of the graph.\n");
194 if (GV.hasInitializer())
195 if (Visited.
insert(GV.getInitializer()).second)
199 dbgs() <<
" Adding functions referenced by global initializers to the "
202 addEdge(EntryEdges.Edges, EntryEdges.EdgeIndexMap,
get(
F),
214#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
231 BPA = std::move(
G.BPA);
232 NodeMap = std::move(
G.NodeMap);
233 EntryEdges = std::move(
G.EntryEdges);
234 SCCBPA = std::move(
G.SCCBPA);
235 SCCMap = std::move(
G.SCCMap);
236 LibFunctions = std::move(
G.LibFunctions);
241#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
243 dbgs() << *
this <<
'\n';
247#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
248void LazyCallGraph::SCC::verify() {
249 assert(OuterRefSCC &&
"Can't have a null RefSCC!");
250 assert(!Nodes.empty() &&
"Can't have an empty SCC!");
252 for (
Node *
N : Nodes) {
253 assert(
N &&
"Can't have a null node!");
254 assert(OuterRefSCC->G->lookupSCC(*
N) ==
this &&
255 "Node does not map to this SCC!");
257 "Must set DFS numbers to -1 when adding a node to an SCC!");
259 "Must set low link to -1 when adding a node to an SCC!");
261 assert(E.getNode().isPopulated() &&
"Can't have an unpopulated node!");
263#ifdef EXPENSIVE_CHECKS
268 while (!Worklist.
empty()) {
270 if (!Visited.
insert(VisitingNode).second)
272 for (Edge &E : (*VisitingNode)->calls())
275 for (
Node *NodeToVisit : Nodes) {
277 "Cannot reach all nodes within SCC");
288 for (
Node &
N : *
this)
289 for (
Edge &E :
N->calls())
290 if (OuterRefSCC->G->lookupSCC(E.getNode()) == &
C)
298 if (
this == &TargetC)
311 for (
Edge &E :
N->calls()) {
312 SCC *CalleeC =
G.lookupSCC(E.getNode());
317 if (CalleeC == &TargetC)
322 if (Visited.
insert(CalleeC).second)
325 }
while (!Worklist.
empty());
333#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
335 dbgs() << *
this <<
'\n';
339#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
340void LazyCallGraph::RefSCC::verify() {
341 assert(
G &&
"Can't have a null graph!");
342 assert(!SCCs.empty() &&
"Can't have an empty SCC!");
346 for (SCC *
C : SCCs) {
347 assert(
C &&
"Can't have a null SCC!");
349 assert(&
C->getOuterRefSCC() ==
this &&
350 "SCC doesn't think it is inside this RefSCC!");
351 bool Inserted = SCCSet.
insert(
C).second;
352 assert(Inserted &&
"Found a duplicate SCC!");
353 auto IndexIt = SCCIndices.find(
C);
354 assert(IndexIt != SCCIndices.end() &&
355 "Found an SCC that doesn't have an index!");
359 for (
auto [
C,
I] : SCCIndices) {
360 assert(
C &&
"Can't have a null SCC in the indices!");
361 assert(SCCSet.
count(
C) &&
"Found an index for an SCC not in the RefSCC!");
362 assert(SCCs[
I] ==
C &&
"Index doesn't point to SCC!");
366 for (
int I = 0,
Size = SCCs.size();
I <
Size; ++
I) {
367 SCC &SourceSCC = *SCCs[
I];
368 for (
Node &
N : SourceSCC)
372 SCC &TargetSCC = *
G->lookupSCC(E.getNode());
373 if (&TargetSCC.getOuterRefSCC() ==
this) {
374 assert(SCCIndices.find(&TargetSCC)->second <=
I &&
375 "Edge between SCCs violates post-order relationship.");
381#ifdef EXPENSIVE_CHECKS
384 for (SCC *
C : SCCs) {
388 for (
Node *
N : Nodes) {
392 while (!Worklist.
empty()) {
394 if (!Visited.
insert(VisitingNode).second)
396 for (Edge &E : **VisitingNode)
399 for (
Node *NodeToVisit : Nodes) {
401 "Cannot reach all nodes within RefSCC");
416 if (
G->lookupRefSCC(E.getNode()) == &RC)
435 for (
SCC &
C : DescendantRC)
438 auto *ChildRC =
G->lookupRefSCC(E.getNode());
441 if (!ChildRC || !Visited.
insert(ChildRC).second)
445 }
while (!Worklist.
empty());
512template <
typename SCCT,
typename PostorderSequenceT,
typename SCCIndexMapT,
513 typename ComputeSourceConnectedSetCallableT,
514 typename ComputeTargetConnectedSetCallableT>
517 SCCT &SourceSCC, SCCT &TargetSCC, PostorderSequenceT &SCCs,
518 SCCIndexMapT &SCCIndices,
519 ComputeSourceConnectedSetCallableT ComputeSourceConnectedSet,
520 ComputeTargetConnectedSetCallableT ComputeTargetConnectedSet) {
521 int SourceIdx = SCCIndices[&SourceSCC];
522 int TargetIdx = SCCIndices[&TargetSCC];
523 assert(SourceIdx < TargetIdx &&
"Cannot have equal indices here!");
528 ComputeSourceConnectedSet(ConnectedSet);
533 auto SourceI = std::stable_partition(
534 SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx + 1,
535 [&ConnectedSet](SCCT *
C) { return !ConnectedSet.count(C); });
536 for (
int I = SourceIdx, E = TargetIdx + 1;
I < E; ++
I)
537 SCCIndices.find(SCCs[
I])->second =
I;
541 if (!ConnectedSet.
count(&TargetSCC)) {
542 assert(SourceI > (SCCs.begin() + SourceIdx) &&
543 "Must have moved the source to fix the post-order.");
544 assert(*std::prev(SourceI) == &TargetSCC &&
545 "Last SCC to move should have bene the target.");
549 return make_range(std::prev(SourceI), std::prev(SourceI));
552 assert(SCCs[TargetIdx] == &TargetSCC &&
553 "Should not have moved target if connected!");
554 SourceIdx = SourceI - SCCs.begin();
555 assert(SCCs[SourceIdx] == &SourceSCC &&
556 "Bad updated index computation for the source SCC!");
561 if (SourceIdx + 1 < TargetIdx) {
562 ConnectedSet.
clear();
563 ComputeTargetConnectedSet(ConnectedSet);
567 auto TargetI = std::stable_partition(
568 SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1,
569 [&ConnectedSet](SCCT *
C) { return ConnectedSet.count(C); });
570 for (
int I = SourceIdx + 1, E = TargetIdx + 1;
I < E; ++
I)
571 SCCIndices.find(SCCs[
I])->second =
I;
572 TargetIdx = std::prev(TargetI) - SCCs.begin();
573 assert(SCCs[TargetIdx] == &TargetSCC &&
574 "Should always end with the target!");
581 return make_range(SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx);
587 assert(!(*SourceN)[TargetN].isCall() &&
"Must start with a ref edge!");
590#ifdef EXPENSIVE_CHECKS
595 SCC &SourceSCC = *
G->lookupSCC(SourceN);
596 SCC &TargetSCC = *
G->lookupSCC(TargetN);
600 if (&SourceSCC == &TargetSCC) {
611 int SourceIdx = SCCIndices[&SourceSCC];
612 int TargetIdx = SCCIndices[&TargetSCC];
613 if (TargetIdx < SourceIdx) {
620#ifdef EXPENSIVE_CHECKS
625 ConnectedSet.insert(&SourceSCC);
626 auto IsConnected = [&](
SCC &
C) {
628 for (
Edge &E :
N->calls())
629 if (ConnectedSet.count(
G->lookupSCC(E.getNode())))
636 make_range(SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1))
638 ConnectedSet.insert(
C);
646#ifdef EXPENSIVE_CHECKS
651 ConnectedSet.insert(&TargetSCC);
660 SCC &EdgeC = *
G->lookupSCC(E.getNode());
664 if (SCCIndices.find(&EdgeC)->second <= SourceIdx)
668 if (ConnectedSet.insert(&EdgeC).second)
671 }
while (!Worklist.
empty());
679 SourceSCC, TargetSCC, SCCs, SCCIndices, ComputeSourceConnectedSet,
680 ComputeTargetConnectedSet);
684 MergeCB(
ArrayRef(MergeRange.begin(), MergeRange.end()));
688 if (MergeRange.empty()) {
694#ifdef EXPENSIVE_CHECKS
706 for (
SCC *
C : MergeRange) {
708 "We merge *into* the target and shouldn't process it here!");
710 TargetSCC.Nodes.append(
C->Nodes.begin(),
C->Nodes.end());
712 G->SCCMap[
N] = &TargetSCC;
719 int IndexOffset = MergeRange.end() - MergeRange.begin();
720 auto EraseEnd = SCCs.erase(MergeRange.begin(), MergeRange.end());
722 SCCIndices[
C] -= IndexOffset;
733 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
735#ifdef EXPENSIVE_CHECKS
740 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
741 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
742 assert(
G->lookupSCC(SourceN) !=
G->lookupSCC(TargetN) &&
743 "Source and Target must be in separate SCCs for this to be trivial!");
746 SourceN->setEdgeKind(TargetN,
Edge::Ref);
751 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
753#ifdef EXPENSIVE_CHECKS
758 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
759 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
761 SCC &TargetSCC = *
G->lookupSCC(TargetN);
762 assert(
G->lookupSCC(SourceN) == &TargetSCC &&
"Source and Target must be in "
763 "the same SCC to require the "
767 SourceN->setEdgeKind(TargetN,
Edge::Ref);
781 SCC &OldSCC = TargetSCC;
788 Worklist.
swap(OldSCC.Nodes);
789 for (
Node *
N : Worklist) {
790 N->DFSNumber =
N->LowLink = 0;
802 TargetN.DFSNumber = TargetN.LowLink = -1;
803 OldSCC.Nodes.push_back(&TargetN);
804 G->SCCMap[&TargetN] = &OldSCC;
807 for (
Node *RootN : Worklist) {
809 "Cannot begin a new root with a non-empty DFS stack!");
811 "Cannot begin a new root with pending nodes for an SCC!");
814 if (RootN->DFSNumber != 0) {
815 assert(RootN->DFSNumber == -1 &&
816 "Shouldn't have any mid-DFS root nodes!");
820 RootN->DFSNumber = RootN->LowLink = 1;
821 int NextDFSNumber = 2;
826 auto E = (*N)->call_end();
828 Node &ChildN =
I->getNode();
829 if (ChildN.DFSNumber == 0) {
834 assert(!
G->SCCMap.count(&ChildN) &&
835 "Found a node with 0 DFS number but already in an SCC!");
836 ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
838 I = (*N)->call_begin();
839 E = (*N)->call_end();
844 if (ChildN.DFSNumber == -1) {
845 if (
G->lookupSCC(ChildN) == &OldSCC) {
850 int OldSize = OldSCC.
size();
851 OldSCC.Nodes.push_back(
N);
852 OldSCC.Nodes.append(PendingSCCStack.
begin(), PendingSCCStack.
end());
853 PendingSCCStack.
clear();
854 while (!DFSStack.
empty())
857 N.DFSNumber =
N.LowLink = -1;
858 G->SCCMap[&
N] = &OldSCC;
872 assert(ChildN.LowLink > 0 &&
"Must have a positive low-link number!");
873 if (ChildN.LowLink <
N->LowLink)
874 N->LowLink = ChildN.LowLink;
889 if (
N->LowLink !=
N->DFSNumber)
894 int RootDFSNumber =
N->DFSNumber;
900 return N->DFSNumber < RootDFSNumber;
905 NewSCCs.
push_back(
G->createSCC(*
this, SCCNodes));
907 N.DFSNumber =
N.LowLink = -1;
908 G->SCCMap[&
N] = NewSCCs.
back();
910 PendingSCCStack.
erase(SCCNodes.end().base(), PendingSCCStack.
end());
911 }
while (!DFSStack.
empty());
918 int OldIdx = SCCIndices[&OldSCC];
919 SCCs.insert(SCCs.begin() + OldIdx, NewSCCs.
begin(), NewSCCs.
end());
924 SCCIndices[SCCs[
Idx]] =
Idx;
927 SCCs.begin() + OldIdx + NewSCCs.
size());
932 assert(!(*SourceN)[TargetN].isCall() &&
"Must start with a ref edge!");
934 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
935 assert(
G->lookupRefSCC(TargetN) !=
this &&
936 "Target must not be in this RefSCC.");
937#ifdef EXPENSIVE_CHECKS
938 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
939 "Target must be a descendant of the Source.");
946#ifdef EXPENSIVE_CHECKS
953 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
955 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
956 assert(
G->lookupRefSCC(TargetN) !=
this &&
957 "Target must not be in this RefSCC.");
958#ifdef EXPENSIVE_CHECKS
959 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
960 "Target must be a descendant of the Source.");
965 SourceN->setEdgeKind(TargetN,
Edge::Ref);
967#ifdef EXPENSIVE_CHECKS
974 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
975 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
977 SourceN->insertEdgeInternal(TargetN,
Edge::Ref);
979#ifdef EXPENSIVE_CHECKS
987 SourceN->insertEdgeInternal(TargetN, EK);
989 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
991 assert(
G->lookupRefSCC(TargetN) !=
this &&
992 "Target must not be in this RefSCC.");
993#ifdef EXPENSIVE_CHECKS
994 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
995 "Target must be a descendant of the Source.");
998#ifdef EXPENSIVE_CHECKS
1005 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
1006 RefSCC &SourceC = *
G->lookupRefSCC(SourceN);
1007 assert(&SourceC !=
this &&
"Source must not be in this RefSCC.");
1008#ifdef EXPENSIVE_CHECKS
1010 "Source must be a descendant of the Target.");
1015#ifdef EXPENSIVE_CHECKS
1020 int SourceIdx =
G->RefSCCIndices[&SourceC];
1021 int TargetIdx =
G->RefSCCIndices[
this];
1022 assert(SourceIdx < TargetIdx &&
1023 "Postorder list doesn't see edge as incoming!");
1033 Set.insert(&SourceC);
1034 auto IsConnected = [&](
RefSCC &RC) {
1038 if (Set.count(
G->lookupRefSCC(E.getNode())))
1045 G->PostOrderRefSCCs.begin() + TargetIdx + 1))
1046 if (IsConnected(*
C))
1062 for (
Edge &E : *
N) {
1063 RefSCC &EdgeRC = *
G->lookupRefSCC(E.getNode());
1064 if (
G->getRefSCCIndex(EdgeRC) <= SourceIdx)
1068 if (Set.insert(&EdgeRC).second)
1071 }
while (!Worklist.
empty());
1080 SourceC, *
this,
G->PostOrderRefSCCs,
G->RefSCCIndices,
1081 ComputeSourceConnectedSet, ComputeTargetConnectedSet);
1094 for (
RefSCC *RC : MergeRange) {
1095 assert(RC !=
this &&
"We're merging into the target RefSCC, so it "
1096 "shouldn't be in the range.");
1102 for (
SCC &InnerC : *RC) {
1103 InnerC.OuterRefSCC =
this;
1104 SCCIndices[&InnerC] = SCCIndex++;
1105 for (
Node &
N : InnerC)
1106 G->SCCMap[&
N] = &InnerC;
1111 if (MergedSCCs.
empty())
1112 MergedSCCs = std::move(RC->SCCs);
1114 MergedSCCs.
append(RC->SCCs.begin(), RC->SCCs.end());
1120 for (
SCC &InnerC : *
this)
1121 SCCIndices[&InnerC] = SCCIndex++;
1122 MergedSCCs.
append(SCCs.begin(), SCCs.end());
1123 SCCs = std::move(MergedSCCs);
1126 for (
RefSCC *RC : MergeRange)
1127 G->RefSCCIndices.erase(RC);
1128 int IndexOffset = MergeRange.
end() - MergeRange.
begin();
1130 G->PostOrderRefSCCs.erase(MergeRange.
begin(), MergeRange.
end());
1132 G->RefSCCIndices[RC] -= IndexOffset;
1136 SourceN->insertEdgeInternal(TargetN,
Edge::Ref);
1142 return DeletedRefSCCs;
1146 assert(
G->lookupRefSCC(SourceN) ==
this &&
1147 "The source must be a member of this RefSCC.");
1148 assert(
G->lookupRefSCC(TargetN) !=
this &&
1149 "The target must not be a member of this RefSCC");
1151#ifdef EXPENSIVE_CHECKS
1157 bool Removed = SourceN->removeEdgeInternal(TargetN);
1159 assert(Removed &&
"Target not in the edge set for this caller?");
1164 ArrayRef<std::pair<Node *, Node *>> Edges) {
1168#ifdef EXPENSIVE_CHECKS
1182 for (
auto [SourceN, TargetN] : Edges) {
1183 assert(!(**SourceN)[*TargetN].isCall() &&
1184 "Cannot remove a call edge, it must first be made a ref edge");
1186 bool Removed = (*SourceN)->removeEdgeInternal(*TargetN);
1188 assert(Removed &&
"Target not in the edge set for this caller?");
1194 if (
llvm::all_of(Edges, [&](std::pair<Node *, Node *> E) {
1195 return E.first == E.second ||
1196 G->lookupSCC(*E.first) ==
G->lookupSCC(*E.second);
1206 int PostOrderNumber = 0;
1211 for (
SCC *
C : SCCs) {
1213 N.DFSNumber =
N.LowLink = 0;
1215 Worklist.
append(
C->Nodes.begin(),
C->Nodes.end());
1221 const int NumRefSCCNodes = Worklist.
size();
1227 "Cannot begin a new root with a non-empty DFS stack!");
1229 "Cannot begin a new root with pending nodes for an SCC!");
1233 if (RootN->DFSNumber != 0) {
1234 assert(RootN->DFSNumber == -1 &&
1235 "Shouldn't have any mid-DFS root nodes!");
1239 RootN->DFSNumber = RootN->LowLink = 1;
1240 int NextDFSNumber = 2;
1245 auto E = (*N)->end();
1247 assert(
N->DFSNumber != 0 &&
"We should always assign a DFS number "
1248 "before processing a node.");
1251 Node &ChildN =
I->getNode();
1252 if (ChildN.DFSNumber == 0) {
1259 ChildN.LowLink = ChildN.DFSNumber = NextDFSNumber++;
1265 if (ChildN.DFSNumber == -1) {
1274 assert(ChildN.LowLink != 0 &&
1275 "Low-link must not be zero with a non-zero DFS number.");
1276 if (ChildN.LowLink >= 0 && ChildN.LowLink <
N->LowLink)
1277 N->LowLink = ChildN.LowLink;
1287 if (
N->LowLink !=
N->DFSNumber) {
1289 "We never found a viable root for a RefSCC to pop off!");
1294 int RefSCCNumber = PostOrderNumber++;
1295 int RootDFSNumber =
N->DFSNumber;
1301 if (
N->DFSNumber < RootDFSNumber)
1309 N->LowLink = RefSCCNumber;
1312 auto RefSCCNodes =
make_range(StackRI.base(), PendingRefSCCStack.
end());
1318 if (
llvm::size(RefSCCNodes) == NumRefSCCNodes) {
1320 for (
Node *
N : RefSCCNodes)
1328 PendingRefSCCStack.
erase(RefSCCNodes.begin(), PendingRefSCCStack.
end());
1329 }
while (!DFSStack.
empty());
1331 assert(DFSStack.
empty() &&
"Didn't flush the entire DFS stack!");
1332 assert(PendingRefSCCStack.
empty() &&
"Didn't flush all pending nodes!");
1333 }
while (!Worklist.
empty());
1335 assert(PostOrderNumber > 1 &&
1336 "Should never finish the DFS when the existing RefSCC remains valid!");
1342 for (
int I = 0;
I < PostOrderNumber; ++
I)
1343 Result.push_back(
G->createRefSCC(*
G));
1352 int Idx =
G->getRefSCCIndex(*
this);
1353 G->PostOrderRefSCCs.erase(
G->PostOrderRefSCCs.begin() +
Idx);
1354 G->PostOrderRefSCCs.insert(
G->PostOrderRefSCCs.begin() +
Idx, Result.begin(),
1356 for (
int I : seq<int>(
Idx,
G->PostOrderRefSCCs.size()))
1357 G->RefSCCIndices[
G->PostOrderRefSCCs[
I]] =
I;
1359 for (
SCC *
C : SCCs) {
1361 int SCCNumber =
C->begin()->LowLink;
1365 assert(
N.LowLink == SCCNumber &&
1366 "Cannot have different numbers for nodes in the same SCC!");
1370 RefSCC &RC = *Result[SCCNumber];
1371 int SCCIndex = RC.SCCs.size();
1372 RC.SCCs.push_back(
C);
1373 RC.SCCIndices[
C] = SCCIndex;
1374 C->OuterRefSCC = &RC;
1383#ifdef EXPENSIVE_CHECKS
1385 for (
RefSCC *RC : Result)
1395#ifdef EXPENSIVE_CHECKS
1400 SCC &SourceC = *
G->lookupSCC(SourceN);
1401 SCC &TargetC = *
G->lookupSCC(TargetN);
1402 if (&SourceC != &TargetC)
1403 assert(SourceC.isAncestorOf(TargetC) &&
1404 "Call edge is not trivial in the SCC graph!");
1408 auto [Iterator, Inserted] =
1409 SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.
size());
1412 Edge &E = SourceN->Edges[Iterator->second];
1423#ifdef EXPENSIVE_CHECKS
1427 RefSCC &SourceRC = *
G->lookupRefSCC(SourceN);
1428 RefSCC &TargetRC = *
G->lookupRefSCC(TargetN);
1429 if (&SourceRC != &TargetRC)
1430 assert(SourceRC.isAncestorOf(TargetRC) &&
1431 "Ref edge is not trivial in the RefSCC graph!");
1435 auto [Iterator, Inserted] =
1436 SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.
size());
1449#ifdef EXPENSIVE_CHECKS
1452 assert(
G->lookupRefSCC(
N) ==
this &&
1453 "Cannot replace the function of a node outside this RefSCC.");
1455 assert(
G->NodeMap.find(&NewF) ==
G->NodeMap.end() &&
1456 "Must not have already walked the new function!'");
1464 assert(&OldF != &NewF &&
"Cannot replace a function with itself!");
1466 "Must have moved all uses from the old function to the new!");
1469 N.replaceFunction(NewF);
1472 G->NodeMap.erase(&OldF);
1473 G->NodeMap[&NewF] = &
N;
1476 if (
G->isLibFunction(OldF)) {
1477 G->LibFunctions.remove(&OldF);
1478 G->LibFunctions.insert(&NewF);
1484 "This method cannot be called after SCCs have been formed!");
1486 return SourceN->insertEdgeInternal(TargetN, EK);
1491 "This method cannot be called after SCCs have been formed!");
1493 bool Removed = SourceN->removeEdgeInternal(TargetN);
1495 assert(Removed &&
"Target not in the edge set for this caller?");
1502 "This routine should only be called on trivially dead functions!");
1507 "Must not remove lib functions from the call graph!");
1509 auto NI = NodeMap.find(&
F);
1510 assert(NI != NodeMap.end() &&
"Removed function should be known!");
1512 Node &
N = *NI->second;
1530 for (
Edge &E : **
N) {
1532 "dead function shouldn't have any outgoing call edges");
1536 RCs[RC].push_back(
N);
1541 for (
auto [RC, DeadNs] : RCs) {
1543 for (
Node *DeadN : DeadNs) {
1544 for (
Edge &E : **DeadN) {
1546 InternalEdgesToRemove.
push_back({DeadN, &E.getNode()});
1548 RC->removeOutgoingEdge(*DeadN, E.getNode());
1553 (void)RC->removeInternalRefEdges(InternalEdgesToRemove);
1554 for (
Node *DeadN : DeadNs) {
1559 DeadRC->G =
nullptr;
1566 EntryEdges.removeEdgeInternal(
N);
1567 SCCMap.erase(SCCMap.find(&
N));
1568 NodeMap.erase(NodeMap.find(DeadF));
1592 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1593 if (
Function *Callee = CB->getCalledFunction()) {
1594 if (Callee == &NewFunction)
1599 for (
Value *
Op :
I.operand_values()) {
1609 bool FoundNewFunction =
false;
1611 if (&
F == &NewFunction)
1612 FoundNewFunction =
true;
1614 assert(FoundNewFunction &&
"No edge from original function to new function");
1623 "Original function's node should already exist");
1624 Node &OriginalN =
get(OriginalFunction);
1628#ifdef EXPENSIVE_CHECKS
1629 OriginalRC->verify();
1634 "New function's node should not already exist");
1635 Node &NewN = initNode(NewFunction);
1639 SCC *NewC =
nullptr;
1640 for (
Edge &E : *NewN) {
1641 Node &EN = E.getNode();
1647 NewC->Nodes.push_back(&NewN);
1653 for (
Edge &E : *NewN) {
1654 Node &EN = E.getNode();
1659 RefSCC *NewRC = OriginalRC;
1670 : NewRC->SCCIndices.size();
1671 NewRC->SCCs.insert(NewRC->SCCs.begin() + InsertIndex, NewC);
1672 for (
int I = InsertIndex,
Size = NewRC->SCCs.size();
I <
Size; ++
I)
1673 NewRC->SCCIndices[NewRC->SCCs[
I]] =
I;
1684 RefSCC *NewRC = createRefSCC(*
this);
1686 NewRC->SCCIndices[NewC] = 0;
1687 NewRC->SCCs.push_back(NewC);
1688 auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1689 PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1690 for (
int I = OriginalRCIndex,
Size = PostOrderRefSCCs.size();
I <
Size; ++
I)
1691 RefSCCIndices[PostOrderRefSCCs[
I]] =
I;
1694 SCCMap[&NewN] = NewC;
1696 OriginalN->insertEdgeInternal(NewN, EK);
1701 assert(!NewFunctions.
empty() &&
"Can't add zero functions");
1703 "Original function's node should already exist");
1704 Node &OriginalN =
get(OriginalFunction);
1707#ifdef EXPENSIVE_CHECKS
1708 OriginalRC->verify();
1710 OriginalRC->verify();
1711 for (
Function *NewFunction : NewFunctions)
1716 bool ExistsRefToOriginalRefSCC =
false;
1718 for (
Function *NewFunction : NewFunctions) {
1719 Node &NewN = initNode(*NewFunction);
1725 for (
Edge &E : *NewN) {
1727 ExistsRefToOriginalRefSCC =
true;
1734 if (ExistsRefToOriginalRefSCC) {
1741 NewRC = createRefSCC(*
this);
1745 auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1746 PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1747 for (
int I = OriginalRCIndex,
Size = PostOrderRefSCCs.size();
I <
Size; ++
I)
1748 RefSCCIndices[PostOrderRefSCCs[
I]] =
I;
1751 for (
Function *NewFunction : NewFunctions) {
1752 Node &NewN =
get(*NewFunction);
1761 auto Index = NewRC->SCCIndices.size();
1762 NewRC->SCCIndices[NewC] =
Index;
1763 NewRC->SCCs.push_back(NewC);
1764 SCCMap[&NewN] = NewC;
1768 for (
Function *F1 : NewFunctions) {
1770 "Expected ref edges from original function to every new function");
1772 for (
Function *F2 : NewFunctions) {
1777 "Edges between new functions must be ref edges");
1784 return *
new (MappedN = BPA.Allocate()) Node(*
this,
F);
1787void LazyCallGraph::updateGraphPtrs() {
1790 for (
auto &FunctionNodePair : NodeMap)
1791 FunctionNodePair.second->G =
this;
1793 for (
auto *RC : PostOrderRefSCCs)
1799 N.DFSNumber =
N.LowLink = -1;
1805template <
typename RootsT,
typename GetBeginT,
typename GetEndT,
1806 typename GetNodeT,
typename FormSCCCallbackT>
1807void LazyCallGraph::buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
1808 GetEndT &&GetEnd, GetNodeT &&GetNode,
1809 FormSCCCallbackT &&FormSCC) {
1810 using EdgeItT =
decltype(GetBegin(std::declval<Node &>()));
1816 for (
Node *RootN : Roots) {
1818 "Cannot begin a new root with a non-empty DFS stack!");
1820 "Cannot begin a new root with pending nodes for an SCC!");
1823 if (RootN->DFSNumber != 0) {
1824 assert(RootN->DFSNumber == -1 &&
1825 "Shouldn't have any mid-DFS root nodes!");
1829 RootN->DFSNumber = RootN->LowLink = 1;
1830 int NextDFSNumber = 2;
1835 auto E = GetEnd(*
N);
1837 Node &ChildN = GetNode(
I);
1838 if (ChildN.DFSNumber == 0) {
1843 ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
1853 if (ChildN.DFSNumber == -1) {
1859 assert(ChildN.LowLink > 0 &&
"Must have a positive low-link number!");
1860 if (ChildN.LowLink <
N->LowLink)
1861 N->LowLink = ChildN.LowLink;
1873 if (
N->LowLink !=
N->DFSNumber)
1878 int RootDFSNumber =
N->DFSNumber;
1882 PendingSCCStack.
rbegin(),
1884 return N->DFSNumber < RootDFSNumber;
1889 PendingSCCStack.
erase(SCCNodes.end().base(), PendingSCCStack.
end());
1890 }
while (!DFSStack.
empty());
1899void LazyCallGraph::buildSCCs(RefSCC &RC, node_stack_range Nodes) {
1900 assert(RC.SCCs.empty() &&
"Already built SCCs!");
1901 assert(RC.SCCIndices.empty() &&
"Already mapped SCC indices!");
1903 for (
Node *
N : Nodes) {
1904 assert(
N->LowLink >= (*Nodes.begin())->LowLink &&
1905 "We cannot have a low link in an SCC lower than its root on the "
1910 N->DFSNumber =
N->LowLink = 0;
1917 Nodes, [](
Node &
N) {
return N->call_begin(); },
1918 [](
Node &
N) {
return N->call_end(); },
1919 [](EdgeSequence::call_iterator
I) ->
Node & {
return I->getNode(); },
1920 [
this, &RC](node_stack_range Nodes) {
1921 RC.SCCs.push_back(createSCC(RC, Nodes));
1922 for (
Node &
N : *RC.SCCs.back()) {
1923 N.DFSNumber =
N.LowLink = -1;
1924 SCCMap[&
N] = RC.SCCs.back();
1929 for (
int I = 0,
Size = RC.SCCs.size();
I <
Size; ++
I)
1930 RC.SCCIndices[RC.SCCs[
I]] =
I;
1934 if (EntryEdges.
empty() || !PostOrderRefSCCs.empty())
1938 assert(RefSCCIndices.empty() &&
"Already mapped RefSCC indices!");
1941 for (
Edge &E : *
this)
1952 [](
Node &
N) {
return N->end(); },
1955 RefSCC *NewRC = createRefSCC(*
this);
1956 buildSCCs(*NewRC, Nodes);
1961 RefSCCIndices.try_emplace(NewRC, PostOrderRefSCCs.size()).second;
1963 assert(Inserted &&
"Cannot already have this RefSCC in the index map!");
1964 PostOrderRefSCCs.push_back(NewRC);
1965#ifdef EXPENSIVE_CHECKS
1974 while (!Worklist.
empty()) {
1978 if (!
F->isDeclaration())
1985 if (isa<BlockAddress>(
C))
1988 for (
Value *
Op :
C->operand_values())
1989 if (Visited.
insert(cast<Constant>(
Op)).second)
1999 OS <<
" Edges in function: " <<
N.getFunction().getName() <<
"\n";
2001 OS <<
" " << (E.isCall() ?
"call" :
"ref ") <<
" -> "
2002 << E.getFunction().getName() <<
"\n";
2008 OS <<
" SCC with " <<
C.size() <<
" functions:\n";
2011 OS <<
" " <<
N.getFunction().getName() <<
"\n";
2015 OS <<
" RefSCC with " <<
C.size() <<
" call SCCs:\n";
2027 OS <<
"Printing the call graph for module: " << M.getModuleIdentifier()
2048 OS <<
" " <<
Name <<
" -> \""
2051 OS <<
" [style=dashed,label=\"ref\"]";
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static void printNode(raw_ostream &OS, LazyCallGraph::Node &N)
static void printRefSCC(raw_ostream &OS, LazyCallGraph::RefSCC &C)
static iterator_range< typename PostorderSequenceT::iterator > updatePostorderSequenceForEdgeInsertion(SCCT &SourceSCC, SCCT &TargetSCC, PostorderSequenceT &SCCs, SCCIndexMapT &SCCIndices, ComputeSourceConnectedSetCallableT ComputeSourceConnectedSet, ComputeTargetConnectedSetCallableT ComputeTargetConnectedSet)
Generic helper that updates a postorder sequence of SCCs for a potentially cycle-introducing edge ins...
static void printNodeDOT(raw_ostream &OS, LazyCallGraph::Node &N)
static LazyCallGraph::Edge::Kind getEdgeKind(Function &OriginalFunction, Function &NewFunction)
static void printSCC(raw_ostream &OS, LazyCallGraph::SCC &C)
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
static bool isKnownLibFunction(Function &F, TargetLibraryInfo &TLI)
Implements a lazy call graph analysis and related passes for the new pass manager.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
LLVM Basic Block Representation.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
An analysis pass which computes the call graph for a module.
LazyCallGraphDOTPrinterPass(raw_ostream &OS)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LazyCallGraphPrinterPass(raw_ostream &OS)
An iterator used for the edges to both entry nodes and child nodes.
The edge sequence object.
A class used to represent edges in the call graph.
bool isCall() const
Test whether the edge represents a direct call to a function.
Kind
The kind of edge in the graph.
Node & getNode() const
Get the call graph node referenced by this edge.
A node in the call graph.
A RefSCC of the call graph.
SmallVector< RefSCC *, 1 > insertIncomingRefEdge(Node &SourceN, Node &TargetN)
Insert an edge whose source is in a descendant RefSCC and target is in this RefSCC.
bool switchInternalEdgeToCall(Node &SourceN, Node &TargetN, function_ref< void(ArrayRef< SCC * > MergedSCCs)> MergeCB={})
Make an existing internal ref edge into a call edge.
bool isAncestorOf(const RefSCC &RC) const
Test if this RefSCC is an ancestor of RC.
void insertTrivialRefEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new ref edge.
bool isDescendantOf(const RefSCC &RC) const
Test if this RefSCC is a descendant of RC.
void switchOutgoingEdgeToCall(Node &SourceN, Node &TargetN)
Make an existing outgoing ref edge into a call edge.
void replaceNodeFunction(Node &N, Function &NewF)
Directly replace a node's function with a new function.
void insertOutgoingEdge(Node &SourceN, Node &TargetN, Edge::Kind EK)
Insert an edge whose parent is in this RefSCC and child is in some child RefSCC.
SmallVector< RefSCC *, 1 > removeInternalRefEdges(ArrayRef< std::pair< Node *, Node * > > Edges)
Remove a list of ref edges which are entirely within this RefSCC.
iterator_range< iterator > switchInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge within a single SCC into a ref edge.
void insertInternalRefEdge(Node &SourceN, Node &TargetN)
Insert a ref edge from one node in this RefSCC to another in this RefSCC.
void insertTrivialCallEdge(Node &SourceN, Node &TargetN)
A convenience wrapper around the above to handle trivial cases of inserting a new call edge.
void removeOutgoingEdge(Node &SourceN, Node &TargetN)
Remove an edge whose source is in this RefSCC and target is not.
void switchOutgoingEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing outgoing call edge into a ref edge.
void switchTrivialInternalEdgeToRef(Node &SourceN, Node &TargetN)
Make an existing internal call edge between separate SCCs into a ref edge.
bool isParentOf(const RefSCC &RC) const
Test if this RefSCC is a parent of RC.
An SCC of the call graph.
bool isAncestorOf(const SCC &C) const
Test if this SCC is an ancestor of C.
bool isParentOf(const SCC &C) const
Test if this SCC is a parent of C.
RefSCC & getOuterRefSCC() const
A lazily constructed view of the call graph of a module.
bool isLibFunction(Function &F) const
Test whether a function is a known and defined library function tracked by the call graph.
RefSCC * lookupRefSCC(Node &N) const
Lookup a function's RefSCC in the graph.
void insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK)
Update the call graph after inserting a new edge.
LazyCallGraph(Module &M, function_ref< TargetLibraryInfo &(Function &)> GetTLI)
Construct a graph for the given module.
static void visitReferences(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, function_ref< void(Function &)> Callback)
Recursively visits the defined functions whose address is reachable from every constant in the Workli...
void markDeadFunction(Function &F)
Mark a function as dead to be removed later by removeDeadFunctions().
void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
void removeDeadFunctions(ArrayRef< Function * > DeadFs)
Remove dead functions from the call graph.
void removeEdge(Node &SourceN, Node &TargetN)
Update the call graph after deleting an edge.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
LazyCallGraph & operator=(LazyCallGraph &&RHS)
bool invalidate(Module &, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &)
void verify()
Verify that every RefSCC is valid.
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void swap(SmallVectorImpl &RHS)
void push_back(const T &Elt)
reverse_iterator rbegin()
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Provides information about what library functions are available for the current target.
bool isKnownVectorFunctionInLibrary(StringRef F) const
Check if the function "F" is listed in a library known to LLVM.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
std::string EscapeString(const std::string &Label)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...