32#ifdef EXPENSIVE_CHECKS
38#define DEBUG_TYPE "lcg"
40template struct LLVM_EXPORT_TEMPLATE Any::TypeId<const LazyCallGraph::SCC *>;
42void LazyCallGraph::EdgeSequence::insertEdgeInternal(
Node &TargetN,
44 EdgeIndexMap.try_emplace(&TargetN, Edges.
size());
48void LazyCallGraph::EdgeSequence::setEdgeKind(
Node &TargetN,
Edge::Kind EK) {
49 Edges[EdgeIndexMap.find(&TargetN)->second].setKind(EK);
52bool LazyCallGraph::EdgeSequence::removeEdgeInternal(
Node &TargetN) {
53 auto IndexMapI = EdgeIndexMap.find(&TargetN);
54 if (IndexMapI == EdgeIndexMap.end())
57 Edges[IndexMapI->second] = Edge();
58 EdgeIndexMap.erase(IndexMapI);
68 LLVM_DEBUG(
dbgs() <<
" Added callable function: " <<
N.getName() <<
"\n");
73 assert(!Edges &&
"Must not have already populated the edges for this node!");
76 <<
"' to the graph.\n");
78 Edges = EdgeSequence();
102 if (
auto *CB = dyn_cast<CallBase>(&
I))
103 if (
Function *Callee = CB->getCalledFunction())
104 if (!
Callee->isDeclaration())
105 if (Callees.
insert(Callee).second) {
107 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(*Callee),
111 for (
Value *
Op :
I.operand_values())
121 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(
F),
127 for (
auto *
F :
G->LibFunctions)
129 addEdge(Edges->Edges, Edges->EdgeIndexMap,
G->get(*
F),
135void LazyCallGraph::Node::replaceFunction(
Function &NewF) {
136 assert(
F != &NewF &&
"Must not replace a function with itself!");
140#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
142 dbgs() << *
this <<
'\n';
158 LLVM_DEBUG(
dbgs() <<
"Building CG for module: " << M.getModuleIdentifier()
161 if (
F.isDeclaration())
167 LibFunctions.insert(&
F);
169 if (
F.hasLocalLinkage())
175 <<
"' to entry set of the graph.\n");
181 for (
auto &
A : M.aliases()) {
182 if (
A.hasLocalLinkage())
184 if (
Function*
F = dyn_cast<Function>(
A.getAliasee())) {
186 <<
"' with alias '" <<
A.getName()
187 <<
"' to entry set of the graph.\n");
196 if (GV.hasInitializer())
197 if (Visited.
insert(GV.getInitializer()).second)
201 dbgs() <<
" Adding functions referenced by global initializers to the "
204 addEdge(EntryEdges.Edges, EntryEdges.EdgeIndexMap,
get(
F),
216#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
233 BPA = std::move(
G.BPA);
234 NodeMap = std::move(
G.NodeMap);
235 EntryEdges = std::move(
G.EntryEdges);
236 SCCBPA = std::move(
G.SCCBPA);
237 SCCMap = std::move(
G.SCCMap);
238 LibFunctions = std::move(
G.LibFunctions);
243#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
245 dbgs() << *
this <<
'\n';
249#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
250void LazyCallGraph::SCC::verify() {
251 assert(OuterRefSCC &&
"Can't have a null RefSCC!");
252 assert(!Nodes.empty() &&
"Can't have an empty SCC!");
254 for (
Node *
N : Nodes) {
255 assert(
N &&
"Can't have a null node!");
256 assert(OuterRefSCC->G->lookupSCC(*
N) ==
this &&
257 "Node does not map to this SCC!");
259 "Must set DFS numbers to -1 when adding a node to an SCC!");
261 "Must set low link to -1 when adding a node to an SCC!");
263 assert(E.getNode().isPopulated() &&
"Can't have an unpopulated node!");
265#ifdef EXPENSIVE_CHECKS
270 while (!Worklist.
empty()) {
272 if (!Visited.
insert(VisitingNode).second)
274 for (Edge &E : (*VisitingNode)->calls())
277 for (
Node *NodeToVisit : Nodes) {
279 "Cannot reach all nodes within SCC");
290 for (
Node &
N : *
this)
291 for (
Edge &E :
N->calls())
292 if (OuterRefSCC->G->lookupSCC(E.getNode()) == &
C)
300 if (
this == &TargetC)
313 for (
Edge &E :
N->calls()) {
314 SCC *CalleeC =
G.lookupSCC(E.getNode());
319 if (CalleeC == &TargetC)
324 if (Visited.
insert(CalleeC).second)
327 }
while (!Worklist.
empty());
335#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
337 dbgs() << *
this <<
'\n';
341#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
342void LazyCallGraph::RefSCC::verify() {
343 assert(
G &&
"Can't have a null graph!");
344 assert(!SCCs.empty() &&
"Can't have an empty SCC!");
348 for (SCC *
C : SCCs) {
349 assert(
C &&
"Can't have a null SCC!");
351 assert(&
C->getOuterRefSCC() ==
this &&
352 "SCC doesn't think it is inside this RefSCC!");
353 bool Inserted = SCCSet.
insert(
C).second;
354 assert(Inserted &&
"Found a duplicate SCC!");
355 auto IndexIt = SCCIndices.find(
C);
356 assert(IndexIt != SCCIndices.end() &&
357 "Found an SCC that doesn't have an index!");
361 for (
auto [
C,
I] : SCCIndices) {
362 assert(
C &&
"Can't have a null SCC in the indices!");
363 assert(SCCSet.
count(
C) &&
"Found an index for an SCC not in the RefSCC!");
364 assert(SCCs[
I] ==
C &&
"Index doesn't point to SCC!");
368 for (
int I = 0,
Size = SCCs.size();
I <
Size; ++
I) {
369 SCC &SourceSCC = *SCCs[
I];
370 for (
Node &
N : SourceSCC)
374 SCC &TargetSCC = *
G->lookupSCC(E.getNode());
375 if (&TargetSCC.getOuterRefSCC() ==
this) {
376 assert(SCCIndices.find(&TargetSCC)->second <=
I &&
377 "Edge between SCCs violates post-order relationship.");
383#ifdef EXPENSIVE_CHECKS
386 for (SCC *
C : SCCs) {
390 for (
Node *
N : Nodes) {
394 while (!Worklist.
empty()) {
396 if (!Visited.
insert(VisitingNode).second)
398 for (Edge &E : **VisitingNode)
401 for (
Node *NodeToVisit : Nodes) {
403 "Cannot reach all nodes within RefSCC");
418 if (
G->lookupRefSCC(E.getNode()) == &RC)
437 for (
SCC &
C : DescendantRC)
440 auto *ChildRC =
G->lookupRefSCC(E.getNode());
443 if (!ChildRC || !Visited.
insert(ChildRC).second)
447 }
while (!Worklist.
empty());
514template <
typename SCCT,
typename PostorderSequenceT,
typename SCCIndexMapT,
515 typename ComputeSourceConnectedSetCallableT,
516 typename ComputeTargetConnectedSetCallableT>
519 SCCT &SourceSCC, SCCT &TargetSCC, PostorderSequenceT &SCCs,
520 SCCIndexMapT &SCCIndices,
521 ComputeSourceConnectedSetCallableT ComputeSourceConnectedSet,
522 ComputeTargetConnectedSetCallableT ComputeTargetConnectedSet) {
523 int SourceIdx = SCCIndices[&SourceSCC];
524 int TargetIdx = SCCIndices[&TargetSCC];
525 assert(SourceIdx < TargetIdx &&
"Cannot have equal indices here!");
530 ComputeSourceConnectedSet(ConnectedSet);
535 auto SourceI = std::stable_partition(
536 SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx + 1,
537 [&ConnectedSet](SCCT *
C) { return !ConnectedSet.count(C); });
538 for (
int I = SourceIdx, E = TargetIdx + 1;
I < E; ++
I)
539 SCCIndices.find(SCCs[
I])->second =
I;
543 if (!ConnectedSet.
count(&TargetSCC)) {
544 assert(SourceI > (SCCs.begin() + SourceIdx) &&
545 "Must have moved the source to fix the post-order.");
546 assert(*std::prev(SourceI) == &TargetSCC &&
547 "Last SCC to move should have bene the target.");
551 return make_range(std::prev(SourceI), std::prev(SourceI));
554 assert(SCCs[TargetIdx] == &TargetSCC &&
555 "Should not have moved target if connected!");
556 SourceIdx = SourceI - SCCs.begin();
557 assert(SCCs[SourceIdx] == &SourceSCC &&
558 "Bad updated index computation for the source SCC!");
563 if (SourceIdx + 1 < TargetIdx) {
564 ConnectedSet.
clear();
565 ComputeTargetConnectedSet(ConnectedSet);
569 auto TargetI = std::stable_partition(
570 SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1,
571 [&ConnectedSet](SCCT *
C) { return ConnectedSet.count(C); });
572 for (
int I = SourceIdx + 1, E = TargetIdx + 1;
I < E; ++
I)
573 SCCIndices.find(SCCs[
I])->second =
I;
574 TargetIdx = std::prev(TargetI) - SCCs.begin();
575 assert(SCCs[TargetIdx] == &TargetSCC &&
576 "Should always end with the target!");
583 return make_range(SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx);
589 assert(!(*SourceN)[TargetN].isCall() &&
"Must start with a ref edge!");
592#ifdef EXPENSIVE_CHECKS
597 SCC &SourceSCC = *
G->lookupSCC(SourceN);
598 SCC &TargetSCC = *
G->lookupSCC(TargetN);
602 if (&SourceSCC == &TargetSCC) {
613 int SourceIdx = SCCIndices[&SourceSCC];
614 int TargetIdx = SCCIndices[&TargetSCC];
615 if (TargetIdx < SourceIdx) {
622#ifdef EXPENSIVE_CHECKS
627 ConnectedSet.insert(&SourceSCC);
628 auto IsConnected = [&](
SCC &
C) {
630 for (
Edge &E :
N->calls())
631 if (ConnectedSet.count(
G->lookupSCC(E.getNode())))
638 make_range(SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1))
640 ConnectedSet.insert(
C);
648#ifdef EXPENSIVE_CHECKS
653 ConnectedSet.insert(&TargetSCC);
662 SCC &EdgeC = *
G->lookupSCC(E.getNode());
666 if (SCCIndices.find(&EdgeC)->second <= SourceIdx)
670 if (ConnectedSet.insert(&EdgeC).second)
673 }
while (!Worklist.
empty());
681 SourceSCC, TargetSCC, SCCs, SCCIndices, ComputeSourceConnectedSet,
682 ComputeTargetConnectedSet);
686 MergeCB(
ArrayRef(MergeRange.begin(), MergeRange.end()));
690 if (MergeRange.empty()) {
696#ifdef EXPENSIVE_CHECKS
708 for (
SCC *
C : MergeRange) {
710 "We merge *into* the target and shouldn't process it here!");
712 TargetSCC.Nodes.append(
C->Nodes.begin(),
C->Nodes.end());
714 G->SCCMap[
N] = &TargetSCC;
721 int IndexOffset = MergeRange.end() - MergeRange.begin();
722 auto EraseEnd = SCCs.erase(MergeRange.begin(), MergeRange.end());
724 SCCIndices[
C] -= IndexOffset;
735 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
737#ifdef EXPENSIVE_CHECKS
742 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
743 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
744 assert(
G->lookupSCC(SourceN) !=
G->lookupSCC(TargetN) &&
745 "Source and Target must be in separate SCCs for this to be trivial!");
748 SourceN->setEdgeKind(TargetN,
Edge::Ref);
753 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
755#ifdef EXPENSIVE_CHECKS
760 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
761 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
763 SCC &TargetSCC = *
G->lookupSCC(TargetN);
764 assert(
G->lookupSCC(SourceN) == &TargetSCC &&
"Source and Target must be in "
765 "the same SCC to require the "
769 SourceN->setEdgeKind(TargetN,
Edge::Ref);
783 SCC &OldSCC = TargetSCC;
790 Worklist.
swap(OldSCC.Nodes);
791 for (
Node *
N : Worklist) {
792 N->DFSNumber =
N->LowLink = 0;
804 TargetN.DFSNumber = TargetN.LowLink = -1;
805 OldSCC.Nodes.push_back(&TargetN);
806 G->SCCMap[&TargetN] = &OldSCC;
809 for (
Node *RootN : Worklist) {
811 "Cannot begin a new root with a non-empty DFS stack!");
813 "Cannot begin a new root with pending nodes for an SCC!");
816 if (RootN->DFSNumber != 0) {
817 assert(RootN->DFSNumber == -1 &&
818 "Shouldn't have any mid-DFS root nodes!");
822 RootN->DFSNumber = RootN->LowLink = 1;
823 int NextDFSNumber = 2;
828 auto E = (*N)->call_end();
830 Node &ChildN =
I->getNode();
831 if (ChildN.DFSNumber == 0) {
836 assert(!
G->SCCMap.count(&ChildN) &&
837 "Found a node with 0 DFS number but already in an SCC!");
838 ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
840 I = (*N)->call_begin();
841 E = (*N)->call_end();
846 if (ChildN.DFSNumber == -1) {
847 if (
G->lookupSCC(ChildN) == &OldSCC) {
852 int OldSize = OldSCC.
size();
853 OldSCC.Nodes.push_back(
N);
854 OldSCC.Nodes.append(PendingSCCStack.
begin(), PendingSCCStack.
end());
855 PendingSCCStack.
clear();
856 while (!DFSStack.
empty())
859 N.DFSNumber =
N.LowLink = -1;
860 G->SCCMap[&
N] = &OldSCC;
874 assert(ChildN.LowLink > 0 &&
"Must have a positive low-link number!");
875 if (ChildN.LowLink <
N->LowLink)
876 N->LowLink = ChildN.LowLink;
891 if (
N->LowLink !=
N->DFSNumber)
896 int RootDFSNumber =
N->DFSNumber;
902 return N->DFSNumber < RootDFSNumber;
907 NewSCCs.
push_back(
G->createSCC(*
this, SCCNodes));
909 N.DFSNumber =
N.LowLink = -1;
910 G->SCCMap[&
N] = NewSCCs.
back();
912 PendingSCCStack.
erase(SCCNodes.end().base(), PendingSCCStack.
end());
913 }
while (!DFSStack.
empty());
920 int OldIdx = SCCIndices[&OldSCC];
921 SCCs.insert(SCCs.begin() + OldIdx, NewSCCs.
begin(), NewSCCs.
end());
926 SCCIndices[SCCs[
Idx]] =
Idx;
929 SCCs.begin() + OldIdx + NewSCCs.
size());
934 assert(!(*SourceN)[TargetN].isCall() &&
"Must start with a ref edge!");
936 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
937 assert(
G->lookupRefSCC(TargetN) !=
this &&
938 "Target must not be in this RefSCC.");
939#ifdef EXPENSIVE_CHECKS
940 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
941 "Target must be a descendant of the Source.");
948#ifdef EXPENSIVE_CHECKS
955 assert((*SourceN)[TargetN].isCall() &&
"Must start with a call edge!");
957 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
958 assert(
G->lookupRefSCC(TargetN) !=
this &&
959 "Target must not be in this RefSCC.");
960#ifdef EXPENSIVE_CHECKS
961 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
962 "Target must be a descendant of the Source.");
967 SourceN->setEdgeKind(TargetN,
Edge::Ref);
969#ifdef EXPENSIVE_CHECKS
976 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
977 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
979 SourceN->insertEdgeInternal(TargetN,
Edge::Ref);
981#ifdef EXPENSIVE_CHECKS
989 SourceN->insertEdgeInternal(TargetN, EK);
991 assert(
G->lookupRefSCC(SourceN) ==
this &&
"Source must be in this RefSCC.");
993 assert(
G->lookupRefSCC(TargetN) !=
this &&
994 "Target must not be in this RefSCC.");
995#ifdef EXPENSIVE_CHECKS
996 assert(
G->lookupRefSCC(TargetN)->isDescendantOf(*
this) &&
997 "Target must be a descendant of the Source.");
1000#ifdef EXPENSIVE_CHECKS
1007 assert(
G->lookupRefSCC(TargetN) ==
this &&
"Target must be in this RefSCC.");
1008 RefSCC &SourceC = *
G->lookupRefSCC(SourceN);
1009 assert(&SourceC !=
this &&
"Source must not be in this RefSCC.");
1010#ifdef EXPENSIVE_CHECKS
1012 "Source must be a descendant of the Target.");
1017#ifdef EXPENSIVE_CHECKS
1022 int SourceIdx =
G->RefSCCIndices[&SourceC];
1023 int TargetIdx =
G->RefSCCIndices[
this];
1024 assert(SourceIdx < TargetIdx &&
1025 "Postorder list doesn't see edge as incoming!");
1035 Set.insert(&SourceC);
1036 auto IsConnected = [&](
RefSCC &RC) {
1040 if (Set.count(
G->lookupRefSCC(E.getNode())))
1047 G->PostOrderRefSCCs.begin() + TargetIdx + 1))
1048 if (IsConnected(*
C))
1064 for (
Edge &E : *
N) {
1065 RefSCC &EdgeRC = *
G->lookupRefSCC(E.getNode());
1066 if (
G->getRefSCCIndex(EdgeRC) <= SourceIdx)
1070 if (Set.insert(&EdgeRC).second)
1073 }
while (!Worklist.
empty());
1082 SourceC, *
this,
G->PostOrderRefSCCs,
G->RefSCCIndices,
1083 ComputeSourceConnectedSet, ComputeTargetConnectedSet);
1096 for (
RefSCC *RC : MergeRange) {
1097 assert(RC !=
this &&
"We're merging into the target RefSCC, so it "
1098 "shouldn't be in the range.");
1104 for (
SCC &InnerC : *RC) {
1105 InnerC.OuterRefSCC =
this;
1106 SCCIndices[&InnerC] = SCCIndex++;
1107 for (
Node &
N : InnerC)
1108 G->SCCMap[&
N] = &InnerC;
1113 if (MergedSCCs.
empty())
1114 MergedSCCs = std::move(RC->SCCs);
1116 MergedSCCs.
append(RC->SCCs.begin(), RC->SCCs.end());
1122 for (
SCC &InnerC : *
this)
1123 SCCIndices[&InnerC] = SCCIndex++;
1124 MergedSCCs.
append(SCCs.begin(), SCCs.end());
1125 SCCs = std::move(MergedSCCs);
1128 for (
RefSCC *RC : MergeRange)
1129 G->RefSCCIndices.erase(RC);
1130 int IndexOffset = MergeRange.
end() - MergeRange.
begin();
1132 G->PostOrderRefSCCs.erase(MergeRange.
begin(), MergeRange.
end());
1134 G->RefSCCIndices[RC] -= IndexOffset;
1138 SourceN->insertEdgeInternal(TargetN,
Edge::Ref);
1144 return DeletedRefSCCs;
1148 assert(
G->lookupRefSCC(SourceN) ==
this &&
1149 "The source must be a member of this RefSCC.");
1150 assert(
G->lookupRefSCC(TargetN) !=
this &&
1151 "The target must not be a member of this RefSCC");
1153#ifdef EXPENSIVE_CHECKS
1159 bool Removed = SourceN->removeEdgeInternal(TargetN);
1161 assert(Removed &&
"Target not in the edge set for this caller?");
1166 ArrayRef<std::pair<Node *, Node *>> Edges) {
1170#ifdef EXPENSIVE_CHECKS
1184 for (
auto [SourceN, TargetN] : Edges) {
1185 assert(!(**SourceN)[*TargetN].isCall() &&
1186 "Cannot remove a call edge, it must first be made a ref edge");
1188 bool Removed = (*SourceN)->removeEdgeInternal(*TargetN);
1190 assert(Removed &&
"Target not in the edge set for this caller?");
1196 if (
llvm::all_of(Edges, [&](std::pair<Node *, Node *> E) {
1197 return E.first == E.second ||
1198 G->lookupSCC(*E.first) ==
G->lookupSCC(*E.second);
1208 int PostOrderNumber = 0;
1213 for (
SCC *
C : SCCs) {
1215 N.DFSNumber =
N.LowLink = 0;
1217 Worklist.
append(
C->Nodes.begin(),
C->Nodes.end());
1223 const int NumRefSCCNodes = Worklist.
size();
1229 "Cannot begin a new root with a non-empty DFS stack!");
1231 "Cannot begin a new root with pending nodes for an SCC!");
1235 if (RootN->DFSNumber != 0) {
1236 assert(RootN->DFSNumber == -1 &&
1237 "Shouldn't have any mid-DFS root nodes!");
1241 RootN->DFSNumber = RootN->LowLink = 1;
1242 int NextDFSNumber = 2;
1247 auto E = (*N)->end();
1249 assert(
N->DFSNumber != 0 &&
"We should always assign a DFS number "
1250 "before processing a node.");
1253 Node &ChildN =
I->getNode();
1254 if (ChildN.DFSNumber == 0) {
1261 ChildN.LowLink = ChildN.DFSNumber = NextDFSNumber++;
1267 if (ChildN.DFSNumber == -1) {
1276 assert(ChildN.LowLink != 0 &&
1277 "Low-link must not be zero with a non-zero DFS number.");
1278 if (ChildN.LowLink >= 0 && ChildN.LowLink <
N->LowLink)
1279 N->LowLink = ChildN.LowLink;
1289 if (
N->LowLink !=
N->DFSNumber) {
1291 "We never found a viable root for a RefSCC to pop off!");
1296 int RefSCCNumber = PostOrderNumber++;
1297 int RootDFSNumber =
N->DFSNumber;
1303 if (
N->DFSNumber < RootDFSNumber)
1311 N->LowLink = RefSCCNumber;
1314 auto RefSCCNodes =
make_range(StackRI.base(), PendingRefSCCStack.
end());
1320 if (
llvm::size(RefSCCNodes) == NumRefSCCNodes) {
1322 for (
Node *
N : RefSCCNodes)
1330 PendingRefSCCStack.
erase(RefSCCNodes.begin(), PendingRefSCCStack.
end());
1331 }
while (!DFSStack.
empty());
1333 assert(DFSStack.
empty() &&
"Didn't flush the entire DFS stack!");
1334 assert(PendingRefSCCStack.
empty() &&
"Didn't flush all pending nodes!");
1335 }
while (!Worklist.
empty());
1337 assert(PostOrderNumber > 1 &&
1338 "Should never finish the DFS when the existing RefSCC remains valid!");
1344 for (
int I = 0;
I < PostOrderNumber; ++
I)
1345 Result.push_back(
G->createRefSCC(*
G));
1354 int Idx =
G->getRefSCCIndex(*
this);
1355 G->PostOrderRefSCCs.erase(
G->PostOrderRefSCCs.begin() +
Idx);
1356 G->PostOrderRefSCCs.insert(
G->PostOrderRefSCCs.begin() +
Idx, Result.begin(),
1358 for (
int I : seq<int>(
Idx,
G->PostOrderRefSCCs.size()))
1359 G->RefSCCIndices[
G->PostOrderRefSCCs[
I]] =
I;
1361 for (
SCC *
C : SCCs) {
1363 int SCCNumber =
C->begin()->LowLink;
1367 assert(
N.LowLink == SCCNumber &&
1368 "Cannot have different numbers for nodes in the same SCC!");
1372 RefSCC &RC = *Result[SCCNumber];
1373 int SCCIndex = RC.SCCs.size();
1374 RC.SCCs.push_back(
C);
1375 RC.SCCIndices[
C] = SCCIndex;
1376 C->OuterRefSCC = &RC;
1385#ifdef EXPENSIVE_CHECKS
1387 for (
RefSCC *RC : Result)
1397#ifdef EXPENSIVE_CHECKS
1402 SCC &SourceC = *
G->lookupSCC(SourceN);
1403 SCC &TargetC = *
G->lookupSCC(TargetN);
1404 if (&SourceC != &TargetC)
1405 assert(SourceC.isAncestorOf(TargetC) &&
1406 "Call edge is not trivial in the SCC graph!");
1410 auto [Iterator, Inserted] =
1411 SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.
size());
1414 Edge &E = SourceN->Edges[Iterator->second];
1425#ifdef EXPENSIVE_CHECKS
1429 RefSCC &SourceRC = *
G->lookupRefSCC(SourceN);
1430 RefSCC &TargetRC = *
G->lookupRefSCC(TargetN);
1431 if (&SourceRC != &TargetRC)
1432 assert(SourceRC.isAncestorOf(TargetRC) &&
1433 "Ref edge is not trivial in the RefSCC graph!");
1437 auto [Iterator, Inserted] =
1438 SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.
size());
1451#ifdef EXPENSIVE_CHECKS
1454 assert(
G->lookupRefSCC(
N) ==
this &&
1455 "Cannot replace the function of a node outside this RefSCC.");
1457 assert(
G->NodeMap.find(&NewF) ==
G->NodeMap.end() &&
1458 "Must not have already walked the new function!'");
1466 assert(&OldF != &NewF &&
"Cannot replace a function with itself!");
1468 "Must have moved all uses from the old function to the new!");
1471 N.replaceFunction(NewF);
1474 G->NodeMap.erase(&OldF);
1475 G->NodeMap[&NewF] = &
N;
1478 if (
G->isLibFunction(OldF)) {
1479 G->LibFunctions.remove(&OldF);
1480 G->LibFunctions.insert(&NewF);
1486 "This method cannot be called after SCCs have been formed!");
1488 return SourceN->insertEdgeInternal(TargetN, EK);
1493 "This method cannot be called after SCCs have been formed!");
1495 bool Removed = SourceN->removeEdgeInternal(TargetN);
1497 assert(Removed &&
"Target not in the edge set for this caller?");
1504 "This routine should only be called on trivially dead functions!");
1509 "Must not remove lib functions from the call graph!");
1511 auto NI = NodeMap.find(&
F);
1512 assert(NI != NodeMap.end() &&
"Removed function should be known!");
1514 Node &
N = *NI->second;
1532 for (
Edge &E : **
N) {
1534 "dead function shouldn't have any outgoing call edges");
1538 RCs[RC].push_back(
N);
1543 for (
auto [RC, DeadNs] : RCs) {
1545 for (
Node *DeadN : DeadNs) {
1546 for (
Edge &E : **DeadN) {
1548 InternalEdgesToRemove.
push_back({DeadN, &E.getNode()});
1550 RC->removeOutgoingEdge(*DeadN, E.getNode());
1555 (void)RC->removeInternalRefEdges(InternalEdgesToRemove);
1556 for (
Node *DeadN : DeadNs) {
1561 DeadRC->G =
nullptr;
1568 EntryEdges.removeEdgeInternal(
N);
1569 SCCMap.erase(SCCMap.find(&
N));
1570 NodeMap.erase(NodeMap.find(DeadF));
1594 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1595 if (
Function *Callee = CB->getCalledFunction()) {
1596 if (Callee == &NewFunction)
1601 for (
Value *
Op :
I.operand_values()) {
1611 bool FoundNewFunction =
false;
1613 if (&
F == &NewFunction)
1614 FoundNewFunction =
true;
1616 assert(FoundNewFunction &&
"No edge from original function to new function");
1625 "Original function's node should already exist");
1626 Node &OriginalN =
get(OriginalFunction);
1630#ifdef EXPENSIVE_CHECKS
1631 OriginalRC->verify();
1636 "New function's node should not already exist");
1637 Node &NewN = initNode(NewFunction);
1641 SCC *NewC =
nullptr;
1642 for (
Edge &E : *NewN) {
1643 Node &EN = E.getNode();
1649 NewC->Nodes.push_back(&NewN);
1655 for (
Edge &E : *NewN) {
1656 Node &EN = E.getNode();
1661 RefSCC *NewRC = OriginalRC;
1672 : NewRC->SCCIndices.size();
1673 NewRC->SCCs.insert(NewRC->SCCs.begin() + InsertIndex, NewC);
1674 for (
int I = InsertIndex,
Size = NewRC->SCCs.size();
I <
Size; ++
I)
1675 NewRC->SCCIndices[NewRC->SCCs[
I]] =
I;
1686 RefSCC *NewRC = createRefSCC(*
this);
1688 NewRC->SCCIndices[NewC] = 0;
1689 NewRC->SCCs.push_back(NewC);
1690 auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1691 PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1692 for (
int I = OriginalRCIndex,
Size = PostOrderRefSCCs.size();
I <
Size; ++
I)
1693 RefSCCIndices[PostOrderRefSCCs[
I]] =
I;
1696 SCCMap[&NewN] = NewC;
1698 OriginalN->insertEdgeInternal(NewN, EK);
1703 assert(!NewFunctions.
empty() &&
"Can't add zero functions");
1705 "Original function's node should already exist");
1706 Node &OriginalN =
get(OriginalFunction);
1709#ifdef EXPENSIVE_CHECKS
1710 OriginalRC->verify();
1712 OriginalRC->verify();
1713 for (
Function *NewFunction : NewFunctions)
1718 bool ExistsRefToOriginalRefSCC =
false;
1720 for (
Function *NewFunction : NewFunctions) {
1721 Node &NewN = initNode(*NewFunction);
1727 for (
Edge &E : *NewN) {
1729 ExistsRefToOriginalRefSCC =
true;
1736 if (ExistsRefToOriginalRefSCC) {
1743 NewRC = createRefSCC(*
this);
1747 auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1748 PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1749 for (
int I = OriginalRCIndex,
Size = PostOrderRefSCCs.size();
I <
Size; ++
I)
1750 RefSCCIndices[PostOrderRefSCCs[
I]] =
I;
1753 for (
Function *NewFunction : NewFunctions) {
1754 Node &NewN =
get(*NewFunction);
1763 auto Index = NewRC->SCCIndices.size();
1764 NewRC->SCCIndices[NewC] = Index;
1765 NewRC->SCCs.push_back(NewC);
1766 SCCMap[&NewN] = NewC;
1770 for (
Function *F1 : NewFunctions) {
1772 "Expected ref edges from original function to every new function");
1774 for (
Function *F2 : NewFunctions) {
1779 "Edges between new functions must be ref edges");
1786 return *
new (MappedN = BPA.Allocate()) Node(*
this,
F);
1789void LazyCallGraph::updateGraphPtrs() {
1792 for (
auto &FunctionNodePair : NodeMap)
1793 FunctionNodePair.second->G =
this;
1795 for (
auto *RC : PostOrderRefSCCs)
1801 N.DFSNumber =
N.LowLink = -1;
1807template <
typename RootsT,
typename GetBeginT,
typename GetEndT,
1808 typename GetNodeT,
typename FormSCCCallbackT>
1809void LazyCallGraph::buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
1810 GetEndT &&GetEnd, GetNodeT &&GetNode,
1811 FormSCCCallbackT &&FormSCC) {
1812 using EdgeItT =
decltype(GetBegin(std::declval<Node &>()));
1818 for (
Node *RootN : Roots) {
1820 "Cannot begin a new root with a non-empty DFS stack!");
1822 "Cannot begin a new root with pending nodes for an SCC!");
1825 if (RootN->DFSNumber != 0) {
1826 assert(RootN->DFSNumber == -1 &&
1827 "Shouldn't have any mid-DFS root nodes!");
1831 RootN->DFSNumber = RootN->LowLink = 1;
1832 int NextDFSNumber = 2;
1837 auto E = GetEnd(*
N);
1839 Node &ChildN = GetNode(
I);
1840 if (ChildN.DFSNumber == 0) {
1845 ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
1855 if (ChildN.DFSNumber == -1) {
1861 assert(ChildN.LowLink > 0 &&
"Must have a positive low-link number!");
1862 if (ChildN.LowLink <
N->LowLink)
1863 N->LowLink = ChildN.LowLink;
1875 if (
N->LowLink !=
N->DFSNumber)
1880 int RootDFSNumber =
N->DFSNumber;
1884 PendingSCCStack.
rbegin(),
1886 return N->DFSNumber < RootDFSNumber;
1891 PendingSCCStack.
erase(SCCNodes.end().base(), PendingSCCStack.
end());
1892 }
while (!DFSStack.
empty());
1901void LazyCallGraph::buildSCCs(RefSCC &RC, node_stack_range Nodes) {
1902 assert(RC.SCCs.empty() &&
"Already built SCCs!");
1903 assert(RC.SCCIndices.empty() &&
"Already mapped SCC indices!");
1905 for (
Node *
N : Nodes) {
1906 assert(
N->LowLink >= (*Nodes.begin())->LowLink &&
1907 "We cannot have a low link in an SCC lower than its root on the "
1912 N->DFSNumber =
N->LowLink = 0;
1919 Nodes, [](
Node &
N) {
return N->call_begin(); },
1920 [](
Node &
N) {
return N->call_end(); },
1921 [](EdgeSequence::call_iterator
I) ->
Node & {
return I->getNode(); },
1922 [
this, &RC](node_stack_range Nodes) {
1923 RC.SCCs.push_back(createSCC(RC, Nodes));
1924 for (
Node &
N : *RC.SCCs.back()) {
1925 N.DFSNumber =
N.LowLink = -1;
1926 SCCMap[&
N] = RC.SCCs.back();
1931 for (
int I = 0,
Size = RC.SCCs.size();
I <
Size; ++
I)
1932 RC.SCCIndices[RC.SCCs[
I]] =
I;
1936 if (EntryEdges.
empty() || !PostOrderRefSCCs.empty())
1940 assert(RefSCCIndices.empty() &&
"Already mapped RefSCC indices!");
1943 for (
Edge &E : *
this)
1954 [](
Node &
N) {
return N->end(); },
1957 RefSCC *NewRC = createRefSCC(*
this);
1958 buildSCCs(*NewRC, Nodes);
1963 RefSCCIndices.try_emplace(NewRC, PostOrderRefSCCs.size()).second;
1965 assert(Inserted &&
"Cannot already have this RefSCC in the index map!");
1966 PostOrderRefSCCs.push_back(NewRC);
1967#ifdef EXPENSIVE_CHECKS
1976 while (!Worklist.
empty()) {
1980 if (!
F->isDeclaration())
1987 if (isa<BlockAddress>(
C))
1990 for (
Value *
Op :
C->operand_values())
1991 if (Visited.
insert(cast<Constant>(
Op)).second)
2001 OS <<
" Edges in function: " <<
N.getFunction().getName() <<
"\n";
2003 OS <<
" " << (E.isCall() ?
"call" :
"ref ") <<
" -> "
2004 << E.getFunction().getName() <<
"\n";
2010 OS <<
" SCC with " <<
C.size() <<
" functions:\n";
2013 OS <<
" " <<
N.getFunction().getName() <<
"\n";
2017 OS <<
" RefSCC with " <<
C.size() <<
" call SCCs:\n";
2029 OS <<
"Printing the call graph for module: " << M.getModuleIdentifier()
2050 OS <<
" " <<
Name <<
" -> \""
2053 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
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
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.
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...