xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/LazyCallGraph.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- LazyCallGraph.cpp - Analysis of a Module's call graph --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/Analysis/LazyCallGraph.h"
10bdd1243dSDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
120b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
130b57cec5SDimitry Andric #include "llvm/ADT/Sequence.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
160b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
1881ad6265SDimitry Andric #include "llvm/IR/Constants.h"
190b57cec5SDimitry Andric #include "llvm/IR/Function.h"
200b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
21e8d8bef9SDimitry Andric #include "llvm/IR/InstIterator.h"
220b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
230b57cec5SDimitry Andric #include "llvm/IR/Module.h"
240b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
250b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
260b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
270b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
280b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric #include <algorithm>
310b57cec5SDimitry Andric 
3281ad6265SDimitry Andric #ifdef EXPENSIVE_CHECKS
3381ad6265SDimitry Andric #include "llvm/ADT/ScopeExit.h"
3481ad6265SDimitry Andric #endif
3581ad6265SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define DEBUG_TYPE "lcg"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric void LazyCallGraph::EdgeSequence::insertEdgeInternal(Node &TargetN,
410b57cec5SDimitry Andric                                                      Edge::Kind EK) {
42bdd1243dSDimitry Andric   EdgeIndexMap.try_emplace(&TargetN, Edges.size());
430b57cec5SDimitry Andric   Edges.emplace_back(TargetN, EK);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric void LazyCallGraph::EdgeSequence::setEdgeKind(Node &TargetN, Edge::Kind EK) {
470b57cec5SDimitry Andric   Edges[EdgeIndexMap.find(&TargetN)->second].setKind(EK);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric bool LazyCallGraph::EdgeSequence::removeEdgeInternal(Node &TargetN) {
510b57cec5SDimitry Andric   auto IndexMapI = EdgeIndexMap.find(&TargetN);
520b57cec5SDimitry Andric   if (IndexMapI == EdgeIndexMap.end())
530b57cec5SDimitry Andric     return false;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   Edges[IndexMapI->second] = Edge();
560b57cec5SDimitry Andric   EdgeIndexMap.erase(IndexMapI);
570b57cec5SDimitry Andric   return true;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric static void addEdge(SmallVectorImpl<LazyCallGraph::Edge> &Edges,
610b57cec5SDimitry Andric                     DenseMap<LazyCallGraph::Node *, int> &EdgeIndexMap,
620b57cec5SDimitry Andric                     LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK) {
63bdd1243dSDimitry Andric   if (!EdgeIndexMap.try_emplace(&N, Edges.size()).second)
640b57cec5SDimitry Andric     return;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "    Added callable function: " << N.getName() << "\n");
670b57cec5SDimitry Andric   Edges.emplace_back(LazyCallGraph::Edge(N, EK));
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric LazyCallGraph::EdgeSequence &LazyCallGraph::Node::populateSlow() {
710b57cec5SDimitry Andric   assert(!Edges && "Must not have already populated the edges for this node!");
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "  Adding functions called by '" << getName()
740b57cec5SDimitry Andric                     << "' to the graph.\n");
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   Edges = EdgeSequence();
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   SmallVector<Constant *, 16> Worklist;
790b57cec5SDimitry Andric   SmallPtrSet<Function *, 4> Callees;
800b57cec5SDimitry Andric   SmallPtrSet<Constant *, 16> Visited;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   // Find all the potential call graph edges in this function. We track both
830b57cec5SDimitry Andric   // actual call edges and indirect references to functions. The direct calls
840b57cec5SDimitry Andric   // are trivially added, but to accumulate the latter we walk the instructions
850b57cec5SDimitry Andric   // and add every operand which is a constant to the worklist to process
860b57cec5SDimitry Andric   // afterward.
870b57cec5SDimitry Andric   //
880b57cec5SDimitry Andric   // Note that we consider *any* function with a definition to be a viable
890b57cec5SDimitry Andric   // edge. Even if the function's definition is subject to replacement by
900b57cec5SDimitry Andric   // some other module (say, a weak definition) there may still be
910b57cec5SDimitry Andric   // optimizations which essentially speculate based on the definition and
920b57cec5SDimitry Andric   // a way to check that the specific definition is in fact the one being
930b57cec5SDimitry Andric   // used. For example, this could be done by moving the weak definition to
940b57cec5SDimitry Andric   // a strong (internal) definition and making the weak definition be an
950b57cec5SDimitry Andric   // alias. Then a test of the address of the weak function against the new
960b57cec5SDimitry Andric   // strong definition's address would be an effective way to determine the
970b57cec5SDimitry Andric   // safety of optimizing a direct call edge.
980b57cec5SDimitry Andric   for (BasicBlock &BB : *F)
990b57cec5SDimitry Andric     for (Instruction &I : BB) {
1005ffd83dbSDimitry Andric       if (auto *CB = dyn_cast<CallBase>(&I))
1015ffd83dbSDimitry Andric         if (Function *Callee = CB->getCalledFunction())
1020b57cec5SDimitry Andric           if (!Callee->isDeclaration())
1030b57cec5SDimitry Andric             if (Callees.insert(Callee).second) {
1040b57cec5SDimitry Andric               Visited.insert(Callee);
1050b57cec5SDimitry Andric               addEdge(Edges->Edges, Edges->EdgeIndexMap, G->get(*Callee),
1060b57cec5SDimitry Andric                       LazyCallGraph::Edge::Call);
1070b57cec5SDimitry Andric             }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric       for (Value *Op : I.operand_values())
1100b57cec5SDimitry Andric         if (Constant *C = dyn_cast<Constant>(Op))
1110b57cec5SDimitry Andric           if (Visited.insert(C).second)
1120b57cec5SDimitry Andric             Worklist.push_back(C);
1130b57cec5SDimitry Andric     }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // We've collected all the constant (and thus potentially function or
116bdd1243dSDimitry Andric   // function containing) operands to all the instructions in the function.
1170b57cec5SDimitry Andric   // Process them (recursively) collecting every function found.
1180b57cec5SDimitry Andric   visitReferences(Worklist, Visited, [&](Function &F) {
1190b57cec5SDimitry Andric     addEdge(Edges->Edges, Edges->EdgeIndexMap, G->get(F),
1200b57cec5SDimitry Andric             LazyCallGraph::Edge::Ref);
1210b57cec5SDimitry Andric   });
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   // Add implicit reference edges to any defined libcall functions (if we
1240b57cec5SDimitry Andric   // haven't found an explicit edge).
1250b57cec5SDimitry Andric   for (auto *F : G->LibFunctions)
1260b57cec5SDimitry Andric     if (!Visited.count(F))
1270b57cec5SDimitry Andric       addEdge(Edges->Edges, Edges->EdgeIndexMap, G->get(*F),
1280b57cec5SDimitry Andric               LazyCallGraph::Edge::Ref);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   return *Edges;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric void LazyCallGraph::Node::replaceFunction(Function &NewF) {
1340b57cec5SDimitry Andric   assert(F != &NewF && "Must not replace a function with itself!");
1350b57cec5SDimitry Andric   F = &NewF;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1390b57cec5SDimitry Andric LLVM_DUMP_METHOD void LazyCallGraph::Node::dump() const {
1400b57cec5SDimitry Andric   dbgs() << *this << '\n';
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric #endif
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric static bool isKnownLibFunction(Function &F, TargetLibraryInfo &TLI) {
1450b57cec5SDimitry Andric   LibFunc LF;
1460b57cec5SDimitry Andric 
1475ffd83dbSDimitry Andric   // Either this is a normal library function or a "vectorizable"
1485ffd83dbSDimitry Andric   // function.  Not using the VFDatabase here because this query
1495ffd83dbSDimitry Andric   // is related only to libraries handled via the TLI.
1505ffd83dbSDimitry Andric   return TLI.getLibFunc(F, LF) ||
1515ffd83dbSDimitry Andric          TLI.isKnownVectorFunctionInLibrary(F.getName());
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1548bcb0991SDimitry Andric LazyCallGraph::LazyCallGraph(
1558bcb0991SDimitry Andric     Module &M, function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1560b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Building CG for module: " << M.getModuleIdentifier()
1570b57cec5SDimitry Andric                     << "\n");
1580b57cec5SDimitry Andric   for (Function &F : M) {
1590b57cec5SDimitry Andric     if (F.isDeclaration())
1600b57cec5SDimitry Andric       continue;
1610b57cec5SDimitry Andric     // If this function is a known lib function to LLVM then we want to
1620b57cec5SDimitry Andric     // synthesize reference edges to it to model the fact that LLVM can turn
1630b57cec5SDimitry Andric     // arbitrary code into a library function call.
1648bcb0991SDimitry Andric     if (isKnownLibFunction(F, GetTLI(F)))
1650b57cec5SDimitry Andric       LibFunctions.insert(&F);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric     if (F.hasLocalLinkage())
1680b57cec5SDimitry Andric       continue;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     // External linkage defined functions have edges to them from other
1710b57cec5SDimitry Andric     // modules.
1720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  Adding '" << F.getName()
1730b57cec5SDimitry Andric                       << "' to entry set of the graph.\n");
1740b57cec5SDimitry Andric     addEdge(EntryEdges.Edges, EntryEdges.EdgeIndexMap, get(F), Edge::Ref);
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   // Externally visible aliases of internal functions are also viable entry
1780b57cec5SDimitry Andric   // edges to the module.
1790b57cec5SDimitry Andric   for (auto &A : M.aliases()) {
1800b57cec5SDimitry Andric     if (A.hasLocalLinkage())
1810b57cec5SDimitry Andric       continue;
1820b57cec5SDimitry Andric     if (Function* F = dyn_cast<Function>(A.getAliasee())) {
1830b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  Adding '" << F->getName()
1840b57cec5SDimitry Andric                         << "' with alias '" << A.getName()
1850b57cec5SDimitry Andric                         << "' to entry set of the graph.\n");
1860b57cec5SDimitry Andric       addEdge(EntryEdges.Edges, EntryEdges.EdgeIndexMap, get(*F), Edge::Ref);
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   // Now add entry nodes for functions reachable via initializers to globals.
1910b57cec5SDimitry Andric   SmallVector<Constant *, 16> Worklist;
1920b57cec5SDimitry Andric   SmallPtrSet<Constant *, 16> Visited;
1930b57cec5SDimitry Andric   for (GlobalVariable &GV : M.globals())
1940b57cec5SDimitry Andric     if (GV.hasInitializer())
1950b57cec5SDimitry Andric       if (Visited.insert(GV.getInitializer()).second)
1960b57cec5SDimitry Andric         Worklist.push_back(GV.getInitializer());
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   LLVM_DEBUG(
1990b57cec5SDimitry Andric       dbgs() << "  Adding functions referenced by global initializers to the "
2000b57cec5SDimitry Andric                 "entry set.\n");
2010b57cec5SDimitry Andric   visitReferences(Worklist, Visited, [&](Function &F) {
2020b57cec5SDimitry Andric     addEdge(EntryEdges.Edges, EntryEdges.EdgeIndexMap, get(F),
2030b57cec5SDimitry Andric             LazyCallGraph::Edge::Ref);
2040b57cec5SDimitry Andric   });
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)
2080b57cec5SDimitry Andric     : BPA(std::move(G.BPA)), NodeMap(std::move(G.NodeMap)),
2090b57cec5SDimitry Andric       EntryEdges(std::move(G.EntryEdges)), SCCBPA(std::move(G.SCCBPA)),
210bdd1243dSDimitry Andric       SCCMap(std::move(G.SCCMap)), LibFunctions(std::move(G.LibFunctions)) {
2110b57cec5SDimitry Andric   updateGraphPtrs();
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
214*0fca6ea1SDimitry Andric #if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
215*0fca6ea1SDimitry Andric void LazyCallGraph::verify() {
216*0fca6ea1SDimitry Andric   for (RefSCC &RC : postorder_ref_sccs()) {
217*0fca6ea1SDimitry Andric     RC.verify();
218*0fca6ea1SDimitry Andric   }
219*0fca6ea1SDimitry Andric }
220*0fca6ea1SDimitry Andric #endif
221*0fca6ea1SDimitry Andric 
2225ffd83dbSDimitry Andric bool LazyCallGraph::invalidate(Module &, const PreservedAnalyses &PA,
2235ffd83dbSDimitry Andric                                ModuleAnalysisManager::Invalidator &) {
2245ffd83dbSDimitry Andric   // Check whether the analysis, all analyses on functions, or the function's
2255ffd83dbSDimitry Andric   // CFG have been preserved.
2265ffd83dbSDimitry Andric   auto PAC = PA.getChecker<llvm::LazyCallGraphAnalysis>();
227349cc55cSDimitry Andric   return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
2285ffd83dbSDimitry Andric }
2295ffd83dbSDimitry Andric 
2300b57cec5SDimitry Andric LazyCallGraph &LazyCallGraph::operator=(LazyCallGraph &&G) {
2310b57cec5SDimitry Andric   BPA = std::move(G.BPA);
2320b57cec5SDimitry Andric   NodeMap = std::move(G.NodeMap);
2330b57cec5SDimitry Andric   EntryEdges = std::move(G.EntryEdges);
2340b57cec5SDimitry Andric   SCCBPA = std::move(G.SCCBPA);
2350b57cec5SDimitry Andric   SCCMap = std::move(G.SCCMap);
2360b57cec5SDimitry Andric   LibFunctions = std::move(G.LibFunctions);
2370b57cec5SDimitry Andric   updateGraphPtrs();
2380b57cec5SDimitry Andric   return *this;
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2420b57cec5SDimitry Andric LLVM_DUMP_METHOD void LazyCallGraph::SCC::dump() const {
2430b57cec5SDimitry Andric   dbgs() << *this << '\n';
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric #endif
2460b57cec5SDimitry Andric 
247fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
2480b57cec5SDimitry Andric void LazyCallGraph::SCC::verify() {
2490b57cec5SDimitry Andric   assert(OuterRefSCC && "Can't have a null RefSCC!");
2500b57cec5SDimitry Andric   assert(!Nodes.empty() && "Can't have an empty SCC!");
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   for (Node *N : Nodes) {
2530b57cec5SDimitry Andric     assert(N && "Can't have a null node!");
2540b57cec5SDimitry Andric     assert(OuterRefSCC->G->lookupSCC(*N) == this &&
2550b57cec5SDimitry Andric            "Node does not map to this SCC!");
2560b57cec5SDimitry Andric     assert(N->DFSNumber == -1 &&
2570b57cec5SDimitry Andric            "Must set DFS numbers to -1 when adding a node to an SCC!");
2580b57cec5SDimitry Andric     assert(N->LowLink == -1 &&
2590b57cec5SDimitry Andric            "Must set low link to -1 when adding a node to an SCC!");
2600b57cec5SDimitry Andric     for (Edge &E : **N)
2610b57cec5SDimitry Andric       assert(E.getNode().isPopulated() && "Can't have an unpopulated node!");
262e8d8bef9SDimitry Andric 
263e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS
264e8d8bef9SDimitry Andric     // Verify that all nodes in this SCC can reach all other nodes.
265e8d8bef9SDimitry Andric     SmallVector<Node *, 4> Worklist;
266e8d8bef9SDimitry Andric     SmallPtrSet<Node *, 4> Visited;
267e8d8bef9SDimitry Andric     Worklist.push_back(N);
268e8d8bef9SDimitry Andric     while (!Worklist.empty()) {
269e8d8bef9SDimitry Andric       Node *VisitingNode = Worklist.pop_back_val();
270e8d8bef9SDimitry Andric       if (!Visited.insert(VisitingNode).second)
271e8d8bef9SDimitry Andric         continue;
272e8d8bef9SDimitry Andric       for (Edge &E : (*VisitingNode)->calls())
273e8d8bef9SDimitry Andric         Worklist.push_back(&E.getNode());
274e8d8bef9SDimitry Andric     }
275e8d8bef9SDimitry Andric     for (Node *NodeToVisit : Nodes) {
276e8d8bef9SDimitry Andric       assert(Visited.contains(NodeToVisit) &&
277e8d8bef9SDimitry Andric              "Cannot reach all nodes within SCC");
278e8d8bef9SDimitry Andric     }
279e8d8bef9SDimitry Andric #endif
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric #endif
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric bool LazyCallGraph::SCC::isParentOf(const SCC &C) const {
2850b57cec5SDimitry Andric   if (this == &C)
2860b57cec5SDimitry Andric     return false;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   for (Node &N : *this)
2890b57cec5SDimitry Andric     for (Edge &E : N->calls())
2900b57cec5SDimitry Andric       if (OuterRefSCC->G->lookupSCC(E.getNode()) == &C)
2910b57cec5SDimitry Andric         return true;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   // No edges found.
2940b57cec5SDimitry Andric   return false;
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric bool LazyCallGraph::SCC::isAncestorOf(const SCC &TargetC) const {
2980b57cec5SDimitry Andric   if (this == &TargetC)
2990b57cec5SDimitry Andric     return false;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   LazyCallGraph &G = *OuterRefSCC->G;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   // Start with this SCC.
3040b57cec5SDimitry Andric   SmallPtrSet<const SCC *, 16> Visited = {this};
3050b57cec5SDimitry Andric   SmallVector<const SCC *, 16> Worklist = {this};
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   // Walk down the graph until we run out of edges or find a path to TargetC.
3080b57cec5SDimitry Andric   do {
3090b57cec5SDimitry Andric     const SCC &C = *Worklist.pop_back_val();
3100b57cec5SDimitry Andric     for (Node &N : C)
3110b57cec5SDimitry Andric       for (Edge &E : N->calls()) {
3120b57cec5SDimitry Andric         SCC *CalleeC = G.lookupSCC(E.getNode());
3130b57cec5SDimitry Andric         if (!CalleeC)
3140b57cec5SDimitry Andric           continue;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric         // If the callee's SCC is the TargetC, we're done.
3170b57cec5SDimitry Andric         if (CalleeC == &TargetC)
3180b57cec5SDimitry Andric           return true;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric         // If this is the first time we've reached this SCC, put it on the
3210b57cec5SDimitry Andric         // worklist to recurse through.
3220b57cec5SDimitry Andric         if (Visited.insert(CalleeC).second)
3230b57cec5SDimitry Andric           Worklist.push_back(CalleeC);
3240b57cec5SDimitry Andric       }
3250b57cec5SDimitry Andric   } while (!Worklist.empty());
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   // No paths found.
3280b57cec5SDimitry Andric   return false;
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric LazyCallGraph::RefSCC::RefSCC(LazyCallGraph &G) : G(&G) {}
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3340b57cec5SDimitry Andric LLVM_DUMP_METHOD void LazyCallGraph::RefSCC::dump() const {
3350b57cec5SDimitry Andric   dbgs() << *this << '\n';
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric #endif
3380b57cec5SDimitry Andric 
339fe6060f1SDimitry Andric #if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
3400b57cec5SDimitry Andric void LazyCallGraph::RefSCC::verify() {
3410b57cec5SDimitry Andric   assert(G && "Can't have a null graph!");
3420b57cec5SDimitry Andric   assert(!SCCs.empty() && "Can't have an empty SCC!");
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   // Verify basic properties of the SCCs.
3450b57cec5SDimitry Andric   SmallPtrSet<SCC *, 4> SCCSet;
3460b57cec5SDimitry Andric   for (SCC *C : SCCs) {
3470b57cec5SDimitry Andric     assert(C && "Can't have a null SCC!");
3480b57cec5SDimitry Andric     C->verify();
3490b57cec5SDimitry Andric     assert(&C->getOuterRefSCC() == this &&
3500b57cec5SDimitry Andric            "SCC doesn't think it is inside this RefSCC!");
3510b57cec5SDimitry Andric     bool Inserted = SCCSet.insert(C).second;
3520b57cec5SDimitry Andric     assert(Inserted && "Found a duplicate SCC!");
3530b57cec5SDimitry Andric     auto IndexIt = SCCIndices.find(C);
3540b57cec5SDimitry Andric     assert(IndexIt != SCCIndices.end() &&
3550b57cec5SDimitry Andric            "Found an SCC that doesn't have an index!");
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Check that our indices map correctly.
359bdd1243dSDimitry Andric   for (auto [C, I] : SCCIndices) {
3600b57cec5SDimitry Andric     assert(C && "Can't have a null SCC in the indices!");
3610b57cec5SDimitry Andric     assert(SCCSet.count(C) && "Found an index for an SCC not in the RefSCC!");
362bdd1243dSDimitry Andric     assert(SCCs[I] == C && "Index doesn't point to SCC!");
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   // Check that the SCCs are in fact in post-order.
366bdd1243dSDimitry Andric   for (int I = 0, Size = SCCs.size(); I < Size; ++I) {
367bdd1243dSDimitry Andric     SCC &SourceSCC = *SCCs[I];
3680b57cec5SDimitry Andric     for (Node &N : SourceSCC)
3690b57cec5SDimitry Andric       for (Edge &E : *N) {
3700b57cec5SDimitry Andric         if (!E.isCall())
3710b57cec5SDimitry Andric           continue;
3720b57cec5SDimitry Andric         SCC &TargetSCC = *G->lookupSCC(E.getNode());
3730b57cec5SDimitry Andric         if (&TargetSCC.getOuterRefSCC() == this) {
374bdd1243dSDimitry Andric           assert(SCCIndices.find(&TargetSCC)->second <= I &&
3750b57cec5SDimitry Andric                  "Edge between SCCs violates post-order relationship.");
3760b57cec5SDimitry Andric           continue;
3770b57cec5SDimitry Andric         }
3780b57cec5SDimitry Andric       }
3790b57cec5SDimitry Andric   }
380e8d8bef9SDimitry Andric 
381e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS
382e8d8bef9SDimitry Andric   // Verify that all nodes in this RefSCC can reach all other nodes.
383e8d8bef9SDimitry Andric   SmallVector<Node *> Nodes;
384e8d8bef9SDimitry Andric   for (SCC *C : SCCs) {
385e8d8bef9SDimitry Andric     for (Node &N : *C)
386e8d8bef9SDimitry Andric       Nodes.push_back(&N);
387e8d8bef9SDimitry Andric   }
388e8d8bef9SDimitry Andric   for (Node *N : Nodes) {
389e8d8bef9SDimitry Andric     SmallVector<Node *, 4> Worklist;
390e8d8bef9SDimitry Andric     SmallPtrSet<Node *, 4> Visited;
391e8d8bef9SDimitry Andric     Worklist.push_back(N);
392e8d8bef9SDimitry Andric     while (!Worklist.empty()) {
393e8d8bef9SDimitry Andric       Node *VisitingNode = Worklist.pop_back_val();
394e8d8bef9SDimitry Andric       if (!Visited.insert(VisitingNode).second)
395e8d8bef9SDimitry Andric         continue;
396e8d8bef9SDimitry Andric       for (Edge &E : **VisitingNode)
397e8d8bef9SDimitry Andric         Worklist.push_back(&E.getNode());
398e8d8bef9SDimitry Andric     }
399e8d8bef9SDimitry Andric     for (Node *NodeToVisit : Nodes) {
400e8d8bef9SDimitry Andric       assert(Visited.contains(NodeToVisit) &&
401e8d8bef9SDimitry Andric              "Cannot reach all nodes within RefSCC");
402e8d8bef9SDimitry Andric     }
403e8d8bef9SDimitry Andric   }
404e8d8bef9SDimitry Andric #endif
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric #endif
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric bool LazyCallGraph::RefSCC::isParentOf(const RefSCC &RC) const {
4090b57cec5SDimitry Andric   if (&RC == this)
4100b57cec5SDimitry Andric     return false;
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   // Search all edges to see if this is a parent.
4130b57cec5SDimitry Andric   for (SCC &C : *this)
4140b57cec5SDimitry Andric     for (Node &N : C)
4150b57cec5SDimitry Andric       for (Edge &E : *N)
4160b57cec5SDimitry Andric         if (G->lookupRefSCC(E.getNode()) == &RC)
4170b57cec5SDimitry Andric           return true;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   return false;
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric bool LazyCallGraph::RefSCC::isAncestorOf(const RefSCC &RC) const {
4230b57cec5SDimitry Andric   if (&RC == this)
4240b57cec5SDimitry Andric     return false;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   // For each descendant of this RefSCC, see if one of its children is the
4270b57cec5SDimitry Andric   // argument. If not, add that descendant to the worklist and continue
4280b57cec5SDimitry Andric   // searching.
4290b57cec5SDimitry Andric   SmallVector<const RefSCC *, 4> Worklist;
4300b57cec5SDimitry Andric   SmallPtrSet<const RefSCC *, 4> Visited;
4310b57cec5SDimitry Andric   Worklist.push_back(this);
4320b57cec5SDimitry Andric   Visited.insert(this);
4330b57cec5SDimitry Andric   do {
4340b57cec5SDimitry Andric     const RefSCC &DescendantRC = *Worklist.pop_back_val();
4350b57cec5SDimitry Andric     for (SCC &C : DescendantRC)
4360b57cec5SDimitry Andric       for (Node &N : C)
4370b57cec5SDimitry Andric         for (Edge &E : *N) {
4380b57cec5SDimitry Andric           auto *ChildRC = G->lookupRefSCC(E.getNode());
4390b57cec5SDimitry Andric           if (ChildRC == &RC)
4400b57cec5SDimitry Andric             return true;
4410b57cec5SDimitry Andric           if (!ChildRC || !Visited.insert(ChildRC).second)
4420b57cec5SDimitry Andric             continue;
4430b57cec5SDimitry Andric           Worklist.push_back(ChildRC);
4440b57cec5SDimitry Andric         }
4450b57cec5SDimitry Andric   } while (!Worklist.empty());
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   return false;
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric /// Generic helper that updates a postorder sequence of SCCs for a potentially
4510b57cec5SDimitry Andric /// cycle-introducing edge insertion.
4520b57cec5SDimitry Andric ///
4530b57cec5SDimitry Andric /// A postorder sequence of SCCs of a directed graph has one fundamental
4540b57cec5SDimitry Andric /// property: all deges in the DAG of SCCs point "up" the sequence. That is,
4550b57cec5SDimitry Andric /// all edges in the SCC DAG point to prior SCCs in the sequence.
4560b57cec5SDimitry Andric ///
4570b57cec5SDimitry Andric /// This routine both updates a postorder sequence and uses that sequence to
4580b57cec5SDimitry Andric /// compute the set of SCCs connected into a cycle. It should only be called to
4590b57cec5SDimitry Andric /// insert a "downward" edge which will require changing the sequence to
4600b57cec5SDimitry Andric /// restore it to a postorder.
4610b57cec5SDimitry Andric ///
4620b57cec5SDimitry Andric /// When inserting an edge from an earlier SCC to a later SCC in some postorder
4630b57cec5SDimitry Andric /// sequence, all of the SCCs which may be impacted are in the closed range of
4640b57cec5SDimitry Andric /// those two within the postorder sequence. The algorithm used here to restore
4650b57cec5SDimitry Andric /// the state is as follows:
4660b57cec5SDimitry Andric ///
4670b57cec5SDimitry Andric /// 1) Starting from the source SCC, construct a set of SCCs which reach the
4680b57cec5SDimitry Andric ///    source SCC consisting of just the source SCC. Then scan toward the
4690b57cec5SDimitry Andric ///    target SCC in postorder and for each SCC, if it has an edge to an SCC
4700b57cec5SDimitry Andric ///    in the set, add it to the set. Otherwise, the source SCC is not
4710b57cec5SDimitry Andric ///    a successor, move it in the postorder sequence to immediately before
4720b57cec5SDimitry Andric ///    the source SCC, shifting the source SCC and all SCCs in the set one
4730b57cec5SDimitry Andric ///    position toward the target SCC. Stop scanning after processing the
4740b57cec5SDimitry Andric ///    target SCC.
4750b57cec5SDimitry Andric /// 2) If the source SCC is now past the target SCC in the postorder sequence,
4760b57cec5SDimitry Andric ///    and thus the new edge will flow toward the start, we are done.
4770b57cec5SDimitry Andric /// 3) Otherwise, starting from the target SCC, walk all edges which reach an
4780b57cec5SDimitry Andric ///    SCC between the source and the target, and add them to the set of
4790b57cec5SDimitry Andric ///    connected SCCs, then recurse through them. Once a complete set of the
4800b57cec5SDimitry Andric ///    SCCs the target connects to is known, hoist the remaining SCCs between
4810b57cec5SDimitry Andric ///    the source and the target to be above the target. Note that there is no
4820b57cec5SDimitry Andric ///    need to process the source SCC, it is already known to connect.
4830b57cec5SDimitry Andric /// 4) At this point, all of the SCCs in the closed range between the source
4840b57cec5SDimitry Andric ///    SCC and the target SCC in the postorder sequence are connected,
4850b57cec5SDimitry Andric ///    including the target SCC and the source SCC. Inserting the edge from
4860b57cec5SDimitry Andric ///    the source SCC to the target SCC will form a cycle out of precisely
4870b57cec5SDimitry Andric ///    these SCCs. Thus we can merge all of the SCCs in this closed range into
4880b57cec5SDimitry Andric ///    a single SCC.
4890b57cec5SDimitry Andric ///
4900b57cec5SDimitry Andric /// This process has various important properties:
4910b57cec5SDimitry Andric /// - Only mutates the SCCs when adding the edge actually changes the SCC
4920b57cec5SDimitry Andric ///   structure.
4930b57cec5SDimitry Andric /// - Never mutates SCCs which are unaffected by the change.
4940b57cec5SDimitry Andric /// - Updates the postorder sequence to correctly satisfy the postorder
4950b57cec5SDimitry Andric ///   constraint after the edge is inserted.
4960b57cec5SDimitry Andric /// - Only reorders SCCs in the closed postorder sequence from the source to
4970b57cec5SDimitry Andric ///   the target, so easy to bound how much has changed even in the ordering.
4980b57cec5SDimitry Andric /// - Big-O is the number of edges in the closed postorder range of SCCs from
4990b57cec5SDimitry Andric ///   source to target.
5000b57cec5SDimitry Andric ///
5010b57cec5SDimitry Andric /// This helper routine, in addition to updating the postorder sequence itself
5020b57cec5SDimitry Andric /// will also update a map from SCCs to indices within that sequence.
5030b57cec5SDimitry Andric ///
5040b57cec5SDimitry Andric /// The sequence and the map must operate on pointers to the SCC type.
5050b57cec5SDimitry Andric ///
5060b57cec5SDimitry Andric /// Two callbacks must be provided. The first computes the subset of SCCs in
5070b57cec5SDimitry Andric /// the postorder closed range from the source to the target which connect to
5080b57cec5SDimitry Andric /// the source SCC via some (transitive) set of edges. The second computes the
5090b57cec5SDimitry Andric /// subset of the same range which the target SCC connects to via some
5100b57cec5SDimitry Andric /// (transitive) set of edges. Both callbacks should populate the set argument
5110b57cec5SDimitry Andric /// provided.
5120b57cec5SDimitry Andric template <typename SCCT, typename PostorderSequenceT, typename SCCIndexMapT,
5130b57cec5SDimitry Andric           typename ComputeSourceConnectedSetCallableT,
5140b57cec5SDimitry Andric           typename ComputeTargetConnectedSetCallableT>
5150b57cec5SDimitry Andric static iterator_range<typename PostorderSequenceT::iterator>
5160b57cec5SDimitry Andric updatePostorderSequenceForEdgeInsertion(
5170b57cec5SDimitry Andric     SCCT &SourceSCC, SCCT &TargetSCC, PostorderSequenceT &SCCs,
5180b57cec5SDimitry Andric     SCCIndexMapT &SCCIndices,
5190b57cec5SDimitry Andric     ComputeSourceConnectedSetCallableT ComputeSourceConnectedSet,
5200b57cec5SDimitry Andric     ComputeTargetConnectedSetCallableT ComputeTargetConnectedSet) {
5210b57cec5SDimitry Andric   int SourceIdx = SCCIndices[&SourceSCC];
5220b57cec5SDimitry Andric   int TargetIdx = SCCIndices[&TargetSCC];
5230b57cec5SDimitry Andric   assert(SourceIdx < TargetIdx && "Cannot have equal indices here!");
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   SmallPtrSet<SCCT *, 4> ConnectedSet;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   // Compute the SCCs which (transitively) reach the source.
5280b57cec5SDimitry Andric   ComputeSourceConnectedSet(ConnectedSet);
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // Partition the SCCs in this part of the port-order sequence so only SCCs
5310b57cec5SDimitry Andric   // connecting to the source remain between it and the target. This is
5320b57cec5SDimitry Andric   // a benign partition as it preserves postorder.
5330b57cec5SDimitry Andric   auto SourceI = std::stable_partition(
5340b57cec5SDimitry Andric       SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx + 1,
5350b57cec5SDimitry Andric       [&ConnectedSet](SCCT *C) { return !ConnectedSet.count(C); });
536bdd1243dSDimitry Andric   for (int I = SourceIdx, E = TargetIdx + 1; I < E; ++I)
537bdd1243dSDimitry Andric     SCCIndices.find(SCCs[I])->second = I;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   // If the target doesn't connect to the source, then we've corrected the
5400b57cec5SDimitry Andric   // post-order and there are no cycles formed.
5410b57cec5SDimitry Andric   if (!ConnectedSet.count(&TargetSCC)) {
5420b57cec5SDimitry Andric     assert(SourceI > (SCCs.begin() + SourceIdx) &&
5430b57cec5SDimitry Andric            "Must have moved the source to fix the post-order.");
5440b57cec5SDimitry Andric     assert(*std::prev(SourceI) == &TargetSCC &&
5450b57cec5SDimitry Andric            "Last SCC to move should have bene the target.");
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric     // Return an empty range at the target SCC indicating there is nothing to
5480b57cec5SDimitry Andric     // merge.
5490b57cec5SDimitry Andric     return make_range(std::prev(SourceI), std::prev(SourceI));
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   assert(SCCs[TargetIdx] == &TargetSCC &&
5530b57cec5SDimitry Andric          "Should not have moved target if connected!");
5540b57cec5SDimitry Andric   SourceIdx = SourceI - SCCs.begin();
5550b57cec5SDimitry Andric   assert(SCCs[SourceIdx] == &SourceSCC &&
5560b57cec5SDimitry Andric          "Bad updated index computation for the source SCC!");
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   // See whether there are any remaining intervening SCCs between the source
5590b57cec5SDimitry Andric   // and target. If so we need to make sure they all are reachable form the
5600b57cec5SDimitry Andric   // target.
5610b57cec5SDimitry Andric   if (SourceIdx + 1 < TargetIdx) {
5620b57cec5SDimitry Andric     ConnectedSet.clear();
5630b57cec5SDimitry Andric     ComputeTargetConnectedSet(ConnectedSet);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric     // Partition SCCs so that only SCCs reached from the target remain between
5660b57cec5SDimitry Andric     // the source and the target. This preserves postorder.
5670b57cec5SDimitry Andric     auto TargetI = std::stable_partition(
5680b57cec5SDimitry Andric         SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1,
5690b57cec5SDimitry Andric         [&ConnectedSet](SCCT *C) { return ConnectedSet.count(C); });
570bdd1243dSDimitry Andric     for (int I = SourceIdx + 1, E = TargetIdx + 1; I < E; ++I)
571bdd1243dSDimitry Andric       SCCIndices.find(SCCs[I])->second = I;
5720b57cec5SDimitry Andric     TargetIdx = std::prev(TargetI) - SCCs.begin();
5730b57cec5SDimitry Andric     assert(SCCs[TargetIdx] == &TargetSCC &&
5740b57cec5SDimitry Andric            "Should always end with the target!");
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   // At this point, we know that connecting source to target forms a cycle
578bdd1243dSDimitry Andric   // because target connects back to source, and we know that all the SCCs
5790b57cec5SDimitry Andric   // between the source and target in the postorder sequence participate in that
5800b57cec5SDimitry Andric   // cycle.
5810b57cec5SDimitry Andric   return make_range(SCCs.begin() + SourceIdx, SCCs.begin() + TargetIdx);
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric 
584bdd1243dSDimitry Andric bool LazyCallGraph::RefSCC::switchInternalEdgeToCall(
5850b57cec5SDimitry Andric     Node &SourceN, Node &TargetN,
5860b57cec5SDimitry Andric     function_ref<void(ArrayRef<SCC *> MergeSCCs)> MergeCB) {
5870b57cec5SDimitry Andric   assert(!(*SourceN)[TargetN].isCall() && "Must start with a ref edge!");
5880b57cec5SDimitry Andric   SmallVector<SCC *, 1> DeletedSCCs;
5890b57cec5SDimitry Andric 
590fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
5910b57cec5SDimitry Andric   verify();
5920b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { verify(); });
5930b57cec5SDimitry Andric #endif
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   SCC &SourceSCC = *G->lookupSCC(SourceN);
5960b57cec5SDimitry Andric   SCC &TargetSCC = *G->lookupSCC(TargetN);
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   // If the two nodes are already part of the same SCC, we're also done as
5990b57cec5SDimitry Andric   // we've just added more connectivity.
6000b57cec5SDimitry Andric   if (&SourceSCC == &TargetSCC) {
6010b57cec5SDimitry Andric     SourceN->setEdgeKind(TargetN, Edge::Call);
6020b57cec5SDimitry Andric     return false; // No new cycle.
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   // At this point we leverage the postorder list of SCCs to detect when the
6060b57cec5SDimitry Andric   // insertion of an edge changes the SCC structure in any way.
6070b57cec5SDimitry Andric   //
6080b57cec5SDimitry Andric   // First and foremost, we can eliminate the need for any changes when the
6090b57cec5SDimitry Andric   // edge is toward the beginning of the postorder sequence because all edges
6100b57cec5SDimitry Andric   // flow in that direction already. Thus adding a new one cannot form a cycle.
6110b57cec5SDimitry Andric   int SourceIdx = SCCIndices[&SourceSCC];
6120b57cec5SDimitry Andric   int TargetIdx = SCCIndices[&TargetSCC];
6130b57cec5SDimitry Andric   if (TargetIdx < SourceIdx) {
6140b57cec5SDimitry Andric     SourceN->setEdgeKind(TargetN, Edge::Call);
6150b57cec5SDimitry Andric     return false; // No new cycle.
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   // Compute the SCCs which (transitively) reach the source.
6190b57cec5SDimitry Andric   auto ComputeSourceConnectedSet = [&](SmallPtrSetImpl<SCC *> &ConnectedSet) {
620fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
6210b57cec5SDimitry Andric     // Check that the RefSCC is still valid before computing this as the
6220b57cec5SDimitry Andric     // results will be nonsensical of we've broken its invariants.
6230b57cec5SDimitry Andric     verify();
6240b57cec5SDimitry Andric #endif
6250b57cec5SDimitry Andric     ConnectedSet.insert(&SourceSCC);
6260b57cec5SDimitry Andric     auto IsConnected = [&](SCC &C) {
6270b57cec5SDimitry Andric       for (Node &N : C)
6280b57cec5SDimitry Andric         for (Edge &E : N->calls())
6290b57cec5SDimitry Andric           if (ConnectedSet.count(G->lookupSCC(E.getNode())))
6300b57cec5SDimitry Andric             return true;
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric       return false;
6330b57cec5SDimitry Andric     };
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     for (SCC *C :
6360b57cec5SDimitry Andric          make_range(SCCs.begin() + SourceIdx + 1, SCCs.begin() + TargetIdx + 1))
6370b57cec5SDimitry Andric       if (IsConnected(*C))
6380b57cec5SDimitry Andric         ConnectedSet.insert(C);
6390b57cec5SDimitry Andric   };
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   // Use a normal worklist to find which SCCs the target connects to. We still
6420b57cec5SDimitry Andric   // bound the search based on the range in the postorder list we care about,
6430b57cec5SDimitry Andric   // but because this is forward connectivity we just "recurse" through the
6440b57cec5SDimitry Andric   // edges.
6450b57cec5SDimitry Andric   auto ComputeTargetConnectedSet = [&](SmallPtrSetImpl<SCC *> &ConnectedSet) {
646fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
6470b57cec5SDimitry Andric     // Check that the RefSCC is still valid before computing this as the
6480b57cec5SDimitry Andric     // results will be nonsensical of we've broken its invariants.
6490b57cec5SDimitry Andric     verify();
6500b57cec5SDimitry Andric #endif
6510b57cec5SDimitry Andric     ConnectedSet.insert(&TargetSCC);
6520b57cec5SDimitry Andric     SmallVector<SCC *, 4> Worklist;
6530b57cec5SDimitry Andric     Worklist.push_back(&TargetSCC);
6540b57cec5SDimitry Andric     do {
6550b57cec5SDimitry Andric       SCC &C = *Worklist.pop_back_val();
6560b57cec5SDimitry Andric       for (Node &N : C)
6570b57cec5SDimitry Andric         for (Edge &E : *N) {
6580b57cec5SDimitry Andric           if (!E.isCall())
6590b57cec5SDimitry Andric             continue;
6600b57cec5SDimitry Andric           SCC &EdgeC = *G->lookupSCC(E.getNode());
6610b57cec5SDimitry Andric           if (&EdgeC.getOuterRefSCC() != this)
6620b57cec5SDimitry Andric             // Not in this RefSCC...
6630b57cec5SDimitry Andric             continue;
6640b57cec5SDimitry Andric           if (SCCIndices.find(&EdgeC)->second <= SourceIdx)
6650b57cec5SDimitry Andric             // Not in the postorder sequence between source and target.
6660b57cec5SDimitry Andric             continue;
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric           if (ConnectedSet.insert(&EdgeC).second)
6690b57cec5SDimitry Andric             Worklist.push_back(&EdgeC);
6700b57cec5SDimitry Andric         }
6710b57cec5SDimitry Andric     } while (!Worklist.empty());
6720b57cec5SDimitry Andric   };
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   // Use a generic helper to update the postorder sequence of SCCs and return
6750b57cec5SDimitry Andric   // a range of any SCCs connected into a cycle by inserting this edge. This
6760b57cec5SDimitry Andric   // routine will also take care of updating the indices into the postorder
6770b57cec5SDimitry Andric   // sequence.
6780b57cec5SDimitry Andric   auto MergeRange = updatePostorderSequenceForEdgeInsertion(
6790b57cec5SDimitry Andric       SourceSCC, TargetSCC, SCCs, SCCIndices, ComputeSourceConnectedSet,
6800b57cec5SDimitry Andric       ComputeTargetConnectedSet);
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Run the user's callback on the merged SCCs before we actually merge them.
6830b57cec5SDimitry Andric   if (MergeCB)
684bdd1243dSDimitry Andric     MergeCB(ArrayRef(MergeRange.begin(), MergeRange.end()));
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   // If the merge range is empty, then adding the edge didn't actually form any
6870b57cec5SDimitry Andric   // new cycles. We're done.
6888bcb0991SDimitry Andric   if (MergeRange.empty()) {
6890b57cec5SDimitry Andric     // Now that the SCC structure is finalized, flip the kind to call.
6900b57cec5SDimitry Andric     SourceN->setEdgeKind(TargetN, Edge::Call);
6910b57cec5SDimitry Andric     return false; // No new cycle.
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
694fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
6950b57cec5SDimitry Andric   // Before merging, check that the RefSCC remains valid after all the
6960b57cec5SDimitry Andric   // postorder updates.
6970b57cec5SDimitry Andric   verify();
6980b57cec5SDimitry Andric #endif
6990b57cec5SDimitry Andric 
700bdd1243dSDimitry Andric   // Otherwise we need to merge all the SCCs in the cycle into a single result
701bdd1243dSDimitry Andric   // SCC.
7020b57cec5SDimitry Andric   //
7030b57cec5SDimitry Andric   // NB: We merge into the target because all of these functions were already
7040b57cec5SDimitry Andric   // reachable from the target, meaning any SCC-wide properties deduced about it
7050b57cec5SDimitry Andric   // other than the set of functions within it will not have changed.
7060b57cec5SDimitry Andric   for (SCC *C : MergeRange) {
7070b57cec5SDimitry Andric     assert(C != &TargetSCC &&
7080b57cec5SDimitry Andric            "We merge *into* the target and shouldn't process it here!");
7090b57cec5SDimitry Andric     SCCIndices.erase(C);
7100b57cec5SDimitry Andric     TargetSCC.Nodes.append(C->Nodes.begin(), C->Nodes.end());
7110b57cec5SDimitry Andric     for (Node *N : C->Nodes)
7120b57cec5SDimitry Andric       G->SCCMap[N] = &TargetSCC;
7130b57cec5SDimitry Andric     C->clear();
7140b57cec5SDimitry Andric     DeletedSCCs.push_back(C);
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   // Erase the merged SCCs from the list and update the indices of the
7180b57cec5SDimitry Andric   // remaining SCCs.
7190b57cec5SDimitry Andric   int IndexOffset = MergeRange.end() - MergeRange.begin();
7200b57cec5SDimitry Andric   auto EraseEnd = SCCs.erase(MergeRange.begin(), MergeRange.end());
7210b57cec5SDimitry Andric   for (SCC *C : make_range(EraseEnd, SCCs.end()))
7220b57cec5SDimitry Andric     SCCIndices[C] -= IndexOffset;
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   // Now that the SCC structure is finalized, flip the kind to call.
7250b57cec5SDimitry Andric   SourceN->setEdgeKind(TargetN, Edge::Call);
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   // And we're done, but we did form a new cycle.
7280b57cec5SDimitry Andric   return true;
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric void LazyCallGraph::RefSCC::switchTrivialInternalEdgeToRef(Node &SourceN,
7320b57cec5SDimitry Andric                                                            Node &TargetN) {
7330b57cec5SDimitry Andric   assert((*SourceN)[TargetN].isCall() && "Must start with a call edge!");
7340b57cec5SDimitry Andric 
735fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
7360b57cec5SDimitry Andric   verify();
7370b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { verify(); });
7380b57cec5SDimitry Andric #endif
7390b57cec5SDimitry Andric 
740bdd1243dSDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
741bdd1243dSDimitry Andric   assert(G->lookupRefSCC(TargetN) == this && "Target must be in this RefSCC.");
7420b57cec5SDimitry Andric   assert(G->lookupSCC(SourceN) != G->lookupSCC(TargetN) &&
7430b57cec5SDimitry Andric          "Source and Target must be in separate SCCs for this to be trivial!");
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   // Set the edge kind.
7460b57cec5SDimitry Andric   SourceN->setEdgeKind(TargetN, Edge::Ref);
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric iterator_range<LazyCallGraph::RefSCC::iterator>
7500b57cec5SDimitry Andric LazyCallGraph::RefSCC::switchInternalEdgeToRef(Node &SourceN, Node &TargetN) {
7510b57cec5SDimitry Andric   assert((*SourceN)[TargetN].isCall() && "Must start with a call edge!");
7520b57cec5SDimitry Andric 
753fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
7540b57cec5SDimitry Andric   verify();
7550b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { verify(); });
7560b57cec5SDimitry Andric #endif
7570b57cec5SDimitry Andric 
758bdd1243dSDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
759bdd1243dSDimitry Andric   assert(G->lookupRefSCC(TargetN) == this && "Target must be in this RefSCC.");
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   SCC &TargetSCC = *G->lookupSCC(TargetN);
7620b57cec5SDimitry Andric   assert(G->lookupSCC(SourceN) == &TargetSCC && "Source and Target must be in "
7630b57cec5SDimitry Andric                                                 "the same SCC to require the "
7640b57cec5SDimitry Andric                                                 "full CG update.");
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   // Set the edge kind.
7670b57cec5SDimitry Andric   SourceN->setEdgeKind(TargetN, Edge::Ref);
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   // Otherwise we are removing a call edge from a single SCC. This may break
7700b57cec5SDimitry Andric   // the cycle. In order to compute the new set of SCCs, we need to do a small
7710b57cec5SDimitry Andric   // DFS over the nodes within the SCC to form any sub-cycles that remain as
7720b57cec5SDimitry Andric   // distinct SCCs and compute a postorder over the resulting SCCs.
7730b57cec5SDimitry Andric   //
7740b57cec5SDimitry Andric   // However, we specially handle the target node. The target node is known to
7750b57cec5SDimitry Andric   // reach all other nodes in the original SCC by definition. This means that
7760b57cec5SDimitry Andric   // we want the old SCC to be replaced with an SCC containing that node as it
7770b57cec5SDimitry Andric   // will be the root of whatever SCC DAG results from the DFS. Assumptions
7780b57cec5SDimitry Andric   // about an SCC such as the set of functions called will continue to hold,
7790b57cec5SDimitry Andric   // etc.
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   SCC &OldSCC = TargetSCC;
7820b57cec5SDimitry Andric   SmallVector<std::pair<Node *, EdgeSequence::call_iterator>, 16> DFSStack;
7830b57cec5SDimitry Andric   SmallVector<Node *, 16> PendingSCCStack;
7840b57cec5SDimitry Andric   SmallVector<SCC *, 4> NewSCCs;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   // Prepare the nodes for a fresh DFS.
7870b57cec5SDimitry Andric   SmallVector<Node *, 16> Worklist;
7880b57cec5SDimitry Andric   Worklist.swap(OldSCC.Nodes);
7890b57cec5SDimitry Andric   for (Node *N : Worklist) {
7900b57cec5SDimitry Andric     N->DFSNumber = N->LowLink = 0;
7910b57cec5SDimitry Andric     G->SCCMap.erase(N);
7920b57cec5SDimitry Andric   }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   // Force the target node to be in the old SCC. This also enables us to take
7950b57cec5SDimitry Andric   // a very significant short-cut in the standard Tarjan walk to re-form SCCs
7960b57cec5SDimitry Andric   // below: whenever we build an edge that reaches the target node, we know
7970b57cec5SDimitry Andric   // that the target node eventually connects back to all other nodes in our
7980b57cec5SDimitry Andric   // walk. As a consequence, we can detect and handle participants in that
7990b57cec5SDimitry Andric   // cycle without walking all the edges that form this connection, and instead
8000b57cec5SDimitry Andric   // by relying on the fundamental guarantee coming into this operation (all
8010b57cec5SDimitry Andric   // nodes are reachable from the target due to previously forming an SCC).
8020b57cec5SDimitry Andric   TargetN.DFSNumber = TargetN.LowLink = -1;
8030b57cec5SDimitry Andric   OldSCC.Nodes.push_back(&TargetN);
8040b57cec5SDimitry Andric   G->SCCMap[&TargetN] = &OldSCC;
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   // Scan down the stack and DFS across the call edges.
8070b57cec5SDimitry Andric   for (Node *RootN : Worklist) {
8080b57cec5SDimitry Andric     assert(DFSStack.empty() &&
8090b57cec5SDimitry Andric            "Cannot begin a new root with a non-empty DFS stack!");
8100b57cec5SDimitry Andric     assert(PendingSCCStack.empty() &&
8110b57cec5SDimitry Andric            "Cannot begin a new root with pending nodes for an SCC!");
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric     // Skip any nodes we've already reached in the DFS.
8140b57cec5SDimitry Andric     if (RootN->DFSNumber != 0) {
8150b57cec5SDimitry Andric       assert(RootN->DFSNumber == -1 &&
8160b57cec5SDimitry Andric              "Shouldn't have any mid-DFS root nodes!");
8170b57cec5SDimitry Andric       continue;
8180b57cec5SDimitry Andric     }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     RootN->DFSNumber = RootN->LowLink = 1;
8210b57cec5SDimitry Andric     int NextDFSNumber = 2;
8220b57cec5SDimitry Andric 
823bdd1243dSDimitry Andric     DFSStack.emplace_back(RootN, (*RootN)->call_begin());
8240b57cec5SDimitry Andric     do {
825bdd1243dSDimitry Andric       auto [N, I] = DFSStack.pop_back_val();
8260b57cec5SDimitry Andric       auto E = (*N)->call_end();
8270b57cec5SDimitry Andric       while (I != E) {
8280b57cec5SDimitry Andric         Node &ChildN = I->getNode();
8290b57cec5SDimitry Andric         if (ChildN.DFSNumber == 0) {
8300b57cec5SDimitry Andric           // We haven't yet visited this child, so descend, pushing the current
8310b57cec5SDimitry Andric           // node onto the stack.
832bdd1243dSDimitry Andric           DFSStack.emplace_back(N, I);
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric           assert(!G->SCCMap.count(&ChildN) &&
8350b57cec5SDimitry Andric                  "Found a node with 0 DFS number but already in an SCC!");
8360b57cec5SDimitry Andric           ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
8370b57cec5SDimitry Andric           N = &ChildN;
8380b57cec5SDimitry Andric           I = (*N)->call_begin();
8390b57cec5SDimitry Andric           E = (*N)->call_end();
8400b57cec5SDimitry Andric           continue;
8410b57cec5SDimitry Andric         }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric         // Check for the child already being part of some component.
8440b57cec5SDimitry Andric         if (ChildN.DFSNumber == -1) {
8450b57cec5SDimitry Andric           if (G->lookupSCC(ChildN) == &OldSCC) {
8460b57cec5SDimitry Andric             // If the child is part of the old SCC, we know that it can reach
8470b57cec5SDimitry Andric             // every other node, so we have formed a cycle. Pull the entire DFS
8480b57cec5SDimitry Andric             // and pending stacks into it. See the comment above about setting
8490b57cec5SDimitry Andric             // up the old SCC for why we do this.
8500b57cec5SDimitry Andric             int OldSize = OldSCC.size();
8510b57cec5SDimitry Andric             OldSCC.Nodes.push_back(N);
8520b57cec5SDimitry Andric             OldSCC.Nodes.append(PendingSCCStack.begin(), PendingSCCStack.end());
8530b57cec5SDimitry Andric             PendingSCCStack.clear();
8540b57cec5SDimitry Andric             while (!DFSStack.empty())
8550b57cec5SDimitry Andric               OldSCC.Nodes.push_back(DFSStack.pop_back_val().first);
856e8d8bef9SDimitry Andric             for (Node &N : drop_begin(OldSCC, OldSize)) {
8570b57cec5SDimitry Andric               N.DFSNumber = N.LowLink = -1;
8580b57cec5SDimitry Andric               G->SCCMap[&N] = &OldSCC;
8590b57cec5SDimitry Andric             }
8600b57cec5SDimitry Andric             N = nullptr;
8610b57cec5SDimitry Andric             break;
8620b57cec5SDimitry Andric           }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric           // If the child has already been added to some child component, it
8650b57cec5SDimitry Andric           // couldn't impact the low-link of this parent because it isn't
8660b57cec5SDimitry Andric           // connected, and thus its low-link isn't relevant so skip it.
8670b57cec5SDimitry Andric           ++I;
8680b57cec5SDimitry Andric           continue;
8690b57cec5SDimitry Andric         }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric         // Track the lowest linked child as the lowest link for this node.
8720b57cec5SDimitry Andric         assert(ChildN.LowLink > 0 && "Must have a positive low-link number!");
8730b57cec5SDimitry Andric         if (ChildN.LowLink < N->LowLink)
8740b57cec5SDimitry Andric           N->LowLink = ChildN.LowLink;
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric         // Move to the next edge.
8770b57cec5SDimitry Andric         ++I;
8780b57cec5SDimitry Andric       }
8790b57cec5SDimitry Andric       if (!N)
8800b57cec5SDimitry Andric         // Cleared the DFS early, start another round.
8810b57cec5SDimitry Andric         break;
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric       // We've finished processing N and its descendants, put it on our pending
8840b57cec5SDimitry Andric       // SCC stack to eventually get merged into an SCC of nodes.
8850b57cec5SDimitry Andric       PendingSCCStack.push_back(N);
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric       // If this node is linked to some lower entry, continue walking up the
8880b57cec5SDimitry Andric       // stack.
8890b57cec5SDimitry Andric       if (N->LowLink != N->DFSNumber)
8900b57cec5SDimitry Andric         continue;
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric       // Otherwise, we've completed an SCC. Append it to our post order list of
8930b57cec5SDimitry Andric       // SCCs.
8940b57cec5SDimitry Andric       int RootDFSNumber = N->DFSNumber;
8950b57cec5SDimitry Andric       // Find the range of the node stack by walking down until we pass the
8960b57cec5SDimitry Andric       // root DFS number.
8970b57cec5SDimitry Andric       auto SCCNodes = make_range(
8980b57cec5SDimitry Andric           PendingSCCStack.rbegin(),
8990b57cec5SDimitry Andric           find_if(reverse(PendingSCCStack), [RootDFSNumber](const Node *N) {
9000b57cec5SDimitry Andric             return N->DFSNumber < RootDFSNumber;
9010b57cec5SDimitry Andric           }));
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric       // Form a new SCC out of these nodes and then clear them off our pending
9040b57cec5SDimitry Andric       // stack.
9050b57cec5SDimitry Andric       NewSCCs.push_back(G->createSCC(*this, SCCNodes));
9060b57cec5SDimitry Andric       for (Node &N : *NewSCCs.back()) {
9070b57cec5SDimitry Andric         N.DFSNumber = N.LowLink = -1;
9080b57cec5SDimitry Andric         G->SCCMap[&N] = NewSCCs.back();
9090b57cec5SDimitry Andric       }
9100b57cec5SDimitry Andric       PendingSCCStack.erase(SCCNodes.end().base(), PendingSCCStack.end());
9110b57cec5SDimitry Andric     } while (!DFSStack.empty());
9120b57cec5SDimitry Andric   }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   // Insert the remaining SCCs before the old one. The old SCC can reach all
9150b57cec5SDimitry Andric   // other SCCs we form because it contains the target node of the removed edge
916bdd1243dSDimitry Andric   // of the old SCC. This means that we will have edges into all the new SCCs,
917bdd1243dSDimitry Andric   // which means the old one must come last for postorder.
9180b57cec5SDimitry Andric   int OldIdx = SCCIndices[&OldSCC];
9190b57cec5SDimitry Andric   SCCs.insert(SCCs.begin() + OldIdx, NewSCCs.begin(), NewSCCs.end());
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   // Update the mapping from SCC* to index to use the new SCC*s, and remove the
9220b57cec5SDimitry Andric   // old SCC from the mapping.
9230b57cec5SDimitry Andric   for (int Idx = OldIdx, Size = SCCs.size(); Idx < Size; ++Idx)
9240b57cec5SDimitry Andric     SCCIndices[SCCs[Idx]] = Idx;
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric   return make_range(SCCs.begin() + OldIdx,
9270b57cec5SDimitry Andric                     SCCs.begin() + OldIdx + NewSCCs.size());
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric void LazyCallGraph::RefSCC::switchOutgoingEdgeToCall(Node &SourceN,
9310b57cec5SDimitry Andric                                                      Node &TargetN) {
9320b57cec5SDimitry Andric   assert(!(*SourceN)[TargetN].isCall() && "Must start with a ref edge!");
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
9350b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) != this &&
9360b57cec5SDimitry Andric          "Target must not be in this RefSCC.");
9370b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
9380b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN)->isDescendantOf(*this) &&
9390b57cec5SDimitry Andric          "Target must be a descendant of the Source.");
9400b57cec5SDimitry Andric #endif
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   // Edges between RefSCCs are the same regardless of call or ref, so we can
9430b57cec5SDimitry Andric   // just flip the edge here.
9440b57cec5SDimitry Andric   SourceN->setEdgeKind(TargetN, Edge::Call);
9450b57cec5SDimitry Andric 
946fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
9470b57cec5SDimitry Andric   verify();
9480b57cec5SDimitry Andric #endif
9490b57cec5SDimitry Andric }
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric void LazyCallGraph::RefSCC::switchOutgoingEdgeToRef(Node &SourceN,
9520b57cec5SDimitry Andric                                                     Node &TargetN) {
9530b57cec5SDimitry Andric   assert((*SourceN)[TargetN].isCall() && "Must start with a call edge!");
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
9560b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) != this &&
9570b57cec5SDimitry Andric          "Target must not be in this RefSCC.");
9580b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
9590b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN)->isDescendantOf(*this) &&
9600b57cec5SDimitry Andric          "Target must be a descendant of the Source.");
9610b57cec5SDimitry Andric #endif
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   // Edges between RefSCCs are the same regardless of call or ref, so we can
9640b57cec5SDimitry Andric   // just flip the edge here.
9650b57cec5SDimitry Andric   SourceN->setEdgeKind(TargetN, Edge::Ref);
9660b57cec5SDimitry Andric 
967fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
9680b57cec5SDimitry Andric   verify();
9690b57cec5SDimitry Andric #endif
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric void LazyCallGraph::RefSCC::insertInternalRefEdge(Node &SourceN,
9730b57cec5SDimitry Andric                                                   Node &TargetN) {
9740b57cec5SDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
9750b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) == this && "Target must be in this RefSCC.");
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   SourceN->insertEdgeInternal(TargetN, Edge::Ref);
9780b57cec5SDimitry Andric 
979fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
9800b57cec5SDimitry Andric   verify();
9810b57cec5SDimitry Andric #endif
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric void LazyCallGraph::RefSCC::insertOutgoingEdge(Node &SourceN, Node &TargetN,
9850b57cec5SDimitry Andric                                                Edge::Kind EK) {
9860b57cec5SDimitry Andric   // First insert it into the caller.
9870b57cec5SDimitry Andric   SourceN->insertEdgeInternal(TargetN, EK);
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric   assert(G->lookupRefSCC(SourceN) == this && "Source must be in this RefSCC.");
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) != this &&
9920b57cec5SDimitry Andric          "Target must not be in this RefSCC.");
9930b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
9940b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN)->isDescendantOf(*this) &&
9950b57cec5SDimitry Andric          "Target must be a descendant of the Source.");
9960b57cec5SDimitry Andric #endif
9970b57cec5SDimitry Andric 
998fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
9990b57cec5SDimitry Andric   verify();
10000b57cec5SDimitry Andric #endif
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric SmallVector<LazyCallGraph::RefSCC *, 1>
10040b57cec5SDimitry Andric LazyCallGraph::RefSCC::insertIncomingRefEdge(Node &SourceN, Node &TargetN) {
10050b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) == this && "Target must be in this RefSCC.");
10060b57cec5SDimitry Andric   RefSCC &SourceC = *G->lookupRefSCC(SourceN);
10070b57cec5SDimitry Andric   assert(&SourceC != this && "Source must not be in this RefSCC.");
10080b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
10090b57cec5SDimitry Andric   assert(SourceC.isDescendantOf(*this) &&
10100b57cec5SDimitry Andric          "Source must be a descendant of the Target.");
10110b57cec5SDimitry Andric #endif
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   SmallVector<RefSCC *, 1> DeletedRefSCCs;
10140b57cec5SDimitry Andric 
1015fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
10160b57cec5SDimitry Andric   verify();
10170b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { verify(); });
10180b57cec5SDimitry Andric #endif
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   int SourceIdx = G->RefSCCIndices[&SourceC];
10210b57cec5SDimitry Andric   int TargetIdx = G->RefSCCIndices[this];
10220b57cec5SDimitry Andric   assert(SourceIdx < TargetIdx &&
10230b57cec5SDimitry Andric          "Postorder list doesn't see edge as incoming!");
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric   // Compute the RefSCCs which (transitively) reach the source. We do this by
10260b57cec5SDimitry Andric   // working backwards from the source using the parent set in each RefSCC,
10270b57cec5SDimitry Andric   // skipping any RefSCCs that don't fall in the postorder range. This has the
10280b57cec5SDimitry Andric   // advantage of walking the sparser parent edge (in high fan-out graphs) but
10290b57cec5SDimitry Andric   // more importantly this removes examining all forward edges in all RefSCCs
10300b57cec5SDimitry Andric   // within the postorder range which aren't in fact connected. Only connected
10310b57cec5SDimitry Andric   // RefSCCs (and their edges) are visited here.
10320b57cec5SDimitry Andric   auto ComputeSourceConnectedSet = [&](SmallPtrSetImpl<RefSCC *> &Set) {
10330b57cec5SDimitry Andric     Set.insert(&SourceC);
10340b57cec5SDimitry Andric     auto IsConnected = [&](RefSCC &RC) {
10350b57cec5SDimitry Andric       for (SCC &C : RC)
10360b57cec5SDimitry Andric         for (Node &N : C)
10370b57cec5SDimitry Andric           for (Edge &E : *N)
10380b57cec5SDimitry Andric             if (Set.count(G->lookupRefSCC(E.getNode())))
10390b57cec5SDimitry Andric               return true;
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric       return false;
10420b57cec5SDimitry Andric     };
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric     for (RefSCC *C : make_range(G->PostOrderRefSCCs.begin() + SourceIdx + 1,
10450b57cec5SDimitry Andric                                 G->PostOrderRefSCCs.begin() + TargetIdx + 1))
10460b57cec5SDimitry Andric       if (IsConnected(*C))
10470b57cec5SDimitry Andric         Set.insert(C);
10480b57cec5SDimitry Andric   };
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   // Use a normal worklist to find which SCCs the target connects to. We still
10510b57cec5SDimitry Andric   // bound the search based on the range in the postorder list we care about,
10520b57cec5SDimitry Andric   // but because this is forward connectivity we just "recurse" through the
10530b57cec5SDimitry Andric   // edges.
10540b57cec5SDimitry Andric   auto ComputeTargetConnectedSet = [&](SmallPtrSetImpl<RefSCC *> &Set) {
10550b57cec5SDimitry Andric     Set.insert(this);
10560b57cec5SDimitry Andric     SmallVector<RefSCC *, 4> Worklist;
10570b57cec5SDimitry Andric     Worklist.push_back(this);
10580b57cec5SDimitry Andric     do {
10590b57cec5SDimitry Andric       RefSCC &RC = *Worklist.pop_back_val();
10600b57cec5SDimitry Andric       for (SCC &C : RC)
10610b57cec5SDimitry Andric         for (Node &N : C)
10620b57cec5SDimitry Andric           for (Edge &E : *N) {
10630b57cec5SDimitry Andric             RefSCC &EdgeRC = *G->lookupRefSCC(E.getNode());
10640b57cec5SDimitry Andric             if (G->getRefSCCIndex(EdgeRC) <= SourceIdx)
10650b57cec5SDimitry Andric               // Not in the postorder sequence between source and target.
10660b57cec5SDimitry Andric               continue;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric             if (Set.insert(&EdgeRC).second)
10690b57cec5SDimitry Andric               Worklist.push_back(&EdgeRC);
10700b57cec5SDimitry Andric           }
10710b57cec5SDimitry Andric     } while (!Worklist.empty());
10720b57cec5SDimitry Andric   };
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // Use a generic helper to update the postorder sequence of RefSCCs and return
10750b57cec5SDimitry Andric   // a range of any RefSCCs connected into a cycle by inserting this edge. This
10760b57cec5SDimitry Andric   // routine will also take care of updating the indices into the postorder
10770b57cec5SDimitry Andric   // sequence.
10780b57cec5SDimitry Andric   iterator_range<SmallVectorImpl<RefSCC *>::iterator> MergeRange =
10790b57cec5SDimitry Andric       updatePostorderSequenceForEdgeInsertion(
10800b57cec5SDimitry Andric           SourceC, *this, G->PostOrderRefSCCs, G->RefSCCIndices,
10810b57cec5SDimitry Andric           ComputeSourceConnectedSet, ComputeTargetConnectedSet);
10820b57cec5SDimitry Andric 
1083bdd1243dSDimitry Andric   // Build a set, so we can do fast tests for whether a RefSCC will end up as
10840b57cec5SDimitry Andric   // part of the merged RefSCC.
10850b57cec5SDimitry Andric   SmallPtrSet<RefSCC *, 16> MergeSet(MergeRange.begin(), MergeRange.end());
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric   // This RefSCC will always be part of that set, so just insert it here.
10880b57cec5SDimitry Andric   MergeSet.insert(this);
10890b57cec5SDimitry Andric 
1090bdd1243dSDimitry Andric   // Now that we have identified all the SCCs which need to be merged into
10910b57cec5SDimitry Andric   // a connected set with the inserted edge, merge all of them into this SCC.
10920b57cec5SDimitry Andric   SmallVector<SCC *, 16> MergedSCCs;
10930b57cec5SDimitry Andric   int SCCIndex = 0;
10940b57cec5SDimitry Andric   for (RefSCC *RC : MergeRange) {
10950b57cec5SDimitry Andric     assert(RC != this && "We're merging into the target RefSCC, so it "
10960b57cec5SDimitry Andric                          "shouldn't be in the range.");
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric     // Walk the inner SCCs to update their up-pointer and walk all the edges to
10990b57cec5SDimitry Andric     // update any parent sets.
11000b57cec5SDimitry Andric     // FIXME: We should try to find a way to avoid this (rather expensive) edge
11010b57cec5SDimitry Andric     // walk by updating the parent sets in some other manner.
11020b57cec5SDimitry Andric     for (SCC &InnerC : *RC) {
11030b57cec5SDimitry Andric       InnerC.OuterRefSCC = this;
11040b57cec5SDimitry Andric       SCCIndices[&InnerC] = SCCIndex++;
11050b57cec5SDimitry Andric       for (Node &N : InnerC)
11060b57cec5SDimitry Andric         G->SCCMap[&N] = &InnerC;
11070b57cec5SDimitry Andric     }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric     // Now merge in the SCCs. We can actually move here so try to reuse storage
11100b57cec5SDimitry Andric     // the first time through.
11110b57cec5SDimitry Andric     if (MergedSCCs.empty())
11120b57cec5SDimitry Andric       MergedSCCs = std::move(RC->SCCs);
11130b57cec5SDimitry Andric     else
11140b57cec5SDimitry Andric       MergedSCCs.append(RC->SCCs.begin(), RC->SCCs.end());
11150b57cec5SDimitry Andric     RC->SCCs.clear();
11160b57cec5SDimitry Andric     DeletedRefSCCs.push_back(RC);
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   // Append our original SCCs to the merged list and move it into place.
11200b57cec5SDimitry Andric   for (SCC &InnerC : *this)
11210b57cec5SDimitry Andric     SCCIndices[&InnerC] = SCCIndex++;
11220b57cec5SDimitry Andric   MergedSCCs.append(SCCs.begin(), SCCs.end());
11230b57cec5SDimitry Andric   SCCs = std::move(MergedSCCs);
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric   // Remove the merged away RefSCCs from the post order sequence.
11260b57cec5SDimitry Andric   for (RefSCC *RC : MergeRange)
11270b57cec5SDimitry Andric     G->RefSCCIndices.erase(RC);
11280b57cec5SDimitry Andric   int IndexOffset = MergeRange.end() - MergeRange.begin();
11290b57cec5SDimitry Andric   auto EraseEnd =
11300b57cec5SDimitry Andric       G->PostOrderRefSCCs.erase(MergeRange.begin(), MergeRange.end());
11310b57cec5SDimitry Andric   for (RefSCC *RC : make_range(EraseEnd, G->PostOrderRefSCCs.end()))
11320b57cec5SDimitry Andric     G->RefSCCIndices[RC] -= IndexOffset;
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   // At this point we have a merged RefSCC with a post-order SCCs list, just
11350b57cec5SDimitry Andric   // connect the nodes to form the new edge.
11360b57cec5SDimitry Andric   SourceN->insertEdgeInternal(TargetN, Edge::Ref);
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   // We return the list of SCCs which were merged so that callers can
11390b57cec5SDimitry Andric   // invalidate any data they have associated with those SCCs. Note that these
11400b57cec5SDimitry Andric   // SCCs are no longer in an interesting state (they are totally empty) but
11410b57cec5SDimitry Andric   // the pointers will remain stable for the life of the graph itself.
11420b57cec5SDimitry Andric   return DeletedRefSCCs;
11430b57cec5SDimitry Andric }
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric void LazyCallGraph::RefSCC::removeOutgoingEdge(Node &SourceN, Node &TargetN) {
11460b57cec5SDimitry Andric   assert(G->lookupRefSCC(SourceN) == this &&
11470b57cec5SDimitry Andric          "The source must be a member of this RefSCC.");
11480b57cec5SDimitry Andric   assert(G->lookupRefSCC(TargetN) != this &&
11490b57cec5SDimitry Andric          "The target must not be a member of this RefSCC");
11500b57cec5SDimitry Andric 
1151fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
11520b57cec5SDimitry Andric   verify();
11530b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { verify(); });
11540b57cec5SDimitry Andric #endif
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   // First remove it from the node.
11570b57cec5SDimitry Andric   bool Removed = SourceN->removeEdgeInternal(TargetN);
11580b57cec5SDimitry Andric   (void)Removed;
11590b57cec5SDimitry Andric   assert(Removed && "Target not in the edge set for this caller?");
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric SmallVector<LazyCallGraph::RefSCC *, 1>
1163*0fca6ea1SDimitry Andric LazyCallGraph::RefSCC::removeInternalRefEdges(
1164*0fca6ea1SDimitry Andric     ArrayRef<std::pair<Node *, Node *>> Edges) {
11650b57cec5SDimitry Andric   // We return a list of the resulting *new* RefSCCs in post-order.
11660b57cec5SDimitry Andric   SmallVector<RefSCC *, 1> Result;
11670b57cec5SDimitry Andric 
1168fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
1169fe6060f1SDimitry Andric   // Verify the RefSCC is valid to start with and that either we return an empty
1170fe6060f1SDimitry Andric   // list of result RefSCCs and this RefSCC remains valid, or we return new
1171fe6060f1SDimitry Andric   // RefSCCs and this RefSCC is dead.
11720b57cec5SDimitry Andric   verify();
11730b57cec5SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() {
11740b57cec5SDimitry Andric     // If we didn't replace our RefSCC with new ones, check that this one
11750b57cec5SDimitry Andric     // remains valid.
11760b57cec5SDimitry Andric     if (G)
11770b57cec5SDimitry Andric       verify();
11780b57cec5SDimitry Andric   });
11790b57cec5SDimitry Andric #endif
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   // First remove the actual edges.
1182*0fca6ea1SDimitry Andric   for (auto [SourceN, TargetN] : Edges) {
1183*0fca6ea1SDimitry Andric     assert(!(**SourceN)[*TargetN].isCall() &&
11840b57cec5SDimitry Andric            "Cannot remove a call edge, it must first be made a ref edge");
11850b57cec5SDimitry Andric 
1186*0fca6ea1SDimitry Andric     bool Removed = (*SourceN)->removeEdgeInternal(*TargetN);
11870b57cec5SDimitry Andric     (void)Removed;
11880b57cec5SDimitry Andric     assert(Removed && "Target not in the edge set for this caller?");
11890b57cec5SDimitry Andric   }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   // Direct self references don't impact the ref graph at all.
11920b57cec5SDimitry Andric   // If all targets are in the same SCC as the source, because no call edges
11930b57cec5SDimitry Andric   // were removed there is no RefSCC structure change.
1194*0fca6ea1SDimitry Andric   if (llvm::all_of(Edges, [&](std::pair<Node *, Node *> E) {
1195*0fca6ea1SDimitry Andric         return E.first == E.second ||
1196*0fca6ea1SDimitry Andric                G->lookupSCC(*E.first) == G->lookupSCC(*E.second);
11970b57cec5SDimitry Andric       }))
11980b57cec5SDimitry Andric     return Result;
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   // We build somewhat synthetic new RefSCCs by providing a postorder mapping
12010b57cec5SDimitry Andric   // for each inner SCC. We store these inside the low-link field of the nodes
12020b57cec5SDimitry Andric   // rather than associated with SCCs because this saves a round-trip through
12030b57cec5SDimitry Andric   // the node->SCC map and in the common case, SCCs are small. We will verify
12040b57cec5SDimitry Andric   // that we always give the same number to every node in the SCC such that
12050b57cec5SDimitry Andric   // these are equivalent.
12060b57cec5SDimitry Andric   int PostOrderNumber = 0;
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric   // Reset all the other nodes to prepare for a DFS over them, and add them to
12090b57cec5SDimitry Andric   // our worklist.
12100b57cec5SDimitry Andric   SmallVector<Node *, 8> Worklist;
12110b57cec5SDimitry Andric   for (SCC *C : SCCs) {
12120b57cec5SDimitry Andric     for (Node &N : *C)
12130b57cec5SDimitry Andric       N.DFSNumber = N.LowLink = 0;
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric     Worklist.append(C->Nodes.begin(), C->Nodes.end());
12160b57cec5SDimitry Andric   }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   // Track the number of nodes in this RefSCC so that we can quickly recognize
12190b57cec5SDimitry Andric   // an important special case of the edge removal not breaking the cycle of
12200b57cec5SDimitry Andric   // this RefSCC.
12210b57cec5SDimitry Andric   const int NumRefSCCNodes = Worklist.size();
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   SmallVector<std::pair<Node *, EdgeSequence::iterator>, 4> DFSStack;
12240b57cec5SDimitry Andric   SmallVector<Node *, 4> PendingRefSCCStack;
12250b57cec5SDimitry Andric   do {
12260b57cec5SDimitry Andric     assert(DFSStack.empty() &&
12270b57cec5SDimitry Andric            "Cannot begin a new root with a non-empty DFS stack!");
12280b57cec5SDimitry Andric     assert(PendingRefSCCStack.empty() &&
12290b57cec5SDimitry Andric            "Cannot begin a new root with pending nodes for an SCC!");
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric     Node *RootN = Worklist.pop_back_val();
12320b57cec5SDimitry Andric     // Skip any nodes we've already reached in the DFS.
12330b57cec5SDimitry Andric     if (RootN->DFSNumber != 0) {
12340b57cec5SDimitry Andric       assert(RootN->DFSNumber == -1 &&
12350b57cec5SDimitry Andric              "Shouldn't have any mid-DFS root nodes!");
12360b57cec5SDimitry Andric       continue;
12370b57cec5SDimitry Andric     }
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric     RootN->DFSNumber = RootN->LowLink = 1;
12400b57cec5SDimitry Andric     int NextDFSNumber = 2;
12410b57cec5SDimitry Andric 
1242bdd1243dSDimitry Andric     DFSStack.emplace_back(RootN, (*RootN)->begin());
12430b57cec5SDimitry Andric     do {
1244bdd1243dSDimitry Andric       auto [N, I] = DFSStack.pop_back_val();
12450b57cec5SDimitry Andric       auto E = (*N)->end();
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric       assert(N->DFSNumber != 0 && "We should always assign a DFS number "
12480b57cec5SDimitry Andric                                   "before processing a node.");
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric       while (I != E) {
12510b57cec5SDimitry Andric         Node &ChildN = I->getNode();
12520b57cec5SDimitry Andric         if (ChildN.DFSNumber == 0) {
12530b57cec5SDimitry Andric           // Mark that we should start at this child when next this node is the
12540b57cec5SDimitry Andric           // top of the stack. We don't start at the next child to ensure this
12550b57cec5SDimitry Andric           // child's lowlink is reflected.
1256bdd1243dSDimitry Andric           DFSStack.emplace_back(N, I);
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric           // Continue, resetting to the child node.
12590b57cec5SDimitry Andric           ChildN.LowLink = ChildN.DFSNumber = NextDFSNumber++;
12600b57cec5SDimitry Andric           N = &ChildN;
12610b57cec5SDimitry Andric           I = ChildN->begin();
12620b57cec5SDimitry Andric           E = ChildN->end();
12630b57cec5SDimitry Andric           continue;
12640b57cec5SDimitry Andric         }
12650b57cec5SDimitry Andric         if (ChildN.DFSNumber == -1) {
12660b57cec5SDimitry Andric           // If this child isn't currently in this RefSCC, no need to process
12670b57cec5SDimitry Andric           // it.
12680b57cec5SDimitry Andric           ++I;
12690b57cec5SDimitry Andric           continue;
12700b57cec5SDimitry Andric         }
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric         // Track the lowest link of the children, if any are still in the stack.
12730b57cec5SDimitry Andric         // Any child not on the stack will have a LowLink of -1.
12740b57cec5SDimitry Andric         assert(ChildN.LowLink != 0 &&
12750b57cec5SDimitry Andric                "Low-link must not be zero with a non-zero DFS number.");
12760b57cec5SDimitry Andric         if (ChildN.LowLink >= 0 && ChildN.LowLink < N->LowLink)
12770b57cec5SDimitry Andric           N->LowLink = ChildN.LowLink;
12780b57cec5SDimitry Andric         ++I;
12790b57cec5SDimitry Andric       }
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric       // We've finished processing N and its descendants, put it on our pending
12820b57cec5SDimitry Andric       // stack to eventually get merged into a RefSCC.
12830b57cec5SDimitry Andric       PendingRefSCCStack.push_back(N);
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric       // If this node is linked to some lower entry, continue walking up the
12860b57cec5SDimitry Andric       // stack.
12870b57cec5SDimitry Andric       if (N->LowLink != N->DFSNumber) {
12880b57cec5SDimitry Andric         assert(!DFSStack.empty() &&
12890b57cec5SDimitry Andric                "We never found a viable root for a RefSCC to pop off!");
12900b57cec5SDimitry Andric         continue;
12910b57cec5SDimitry Andric       }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric       // Otherwise, form a new RefSCC from the top of the pending node stack.
12940b57cec5SDimitry Andric       int RefSCCNumber = PostOrderNumber++;
12950b57cec5SDimitry Andric       int RootDFSNumber = N->DFSNumber;
12960b57cec5SDimitry Andric 
12970b57cec5SDimitry Andric       // Find the range of the node stack by walking down until we pass the
12980b57cec5SDimitry Andric       // root DFS number. Update the DFS numbers and low link numbers in the
12990b57cec5SDimitry Andric       // process to avoid re-walking this list where possible.
13000b57cec5SDimitry Andric       auto StackRI = find_if(reverse(PendingRefSCCStack), [&](Node *N) {
13010b57cec5SDimitry Andric         if (N->DFSNumber < RootDFSNumber)
13020b57cec5SDimitry Andric           // We've found the bottom.
13030b57cec5SDimitry Andric           return true;
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric         // Update this node and keep scanning.
13060b57cec5SDimitry Andric         N->DFSNumber = -1;
13070b57cec5SDimitry Andric         // Save the post-order number in the lowlink field so that we can use
13080b57cec5SDimitry Andric         // it to map SCCs into new RefSCCs after we finish the DFS.
13090b57cec5SDimitry Andric         N->LowLink = RefSCCNumber;
13100b57cec5SDimitry Andric         return false;
13110b57cec5SDimitry Andric       });
13120b57cec5SDimitry Andric       auto RefSCCNodes = make_range(StackRI.base(), PendingRefSCCStack.end());
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric       // If we find a cycle containing all nodes originally in this RefSCC then
13150b57cec5SDimitry Andric       // the removal hasn't changed the structure at all. This is an important
1316bdd1243dSDimitry Andric       // special case, and we can directly exit the entire routine more
13170b57cec5SDimitry Andric       // efficiently as soon as we discover it.
13180b57cec5SDimitry Andric       if (llvm::size(RefSCCNodes) == NumRefSCCNodes) {
13190b57cec5SDimitry Andric         // Clear out the low link field as we won't need it.
13200b57cec5SDimitry Andric         for (Node *N : RefSCCNodes)
13210b57cec5SDimitry Andric           N->LowLink = -1;
13220b57cec5SDimitry Andric         // Return the empty result immediately.
13230b57cec5SDimitry Andric         return Result;
13240b57cec5SDimitry Andric       }
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric       // We've already marked the nodes internally with the RefSCC number so
13270b57cec5SDimitry Andric       // just clear them off the stack and continue.
13280b57cec5SDimitry Andric       PendingRefSCCStack.erase(RefSCCNodes.begin(), PendingRefSCCStack.end());
13290b57cec5SDimitry Andric     } while (!DFSStack.empty());
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric     assert(DFSStack.empty() && "Didn't flush the entire DFS stack!");
13320b57cec5SDimitry Andric     assert(PendingRefSCCStack.empty() && "Didn't flush all pending nodes!");
13330b57cec5SDimitry Andric   } while (!Worklist.empty());
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   assert(PostOrderNumber > 1 &&
13360b57cec5SDimitry Andric          "Should never finish the DFS when the existing RefSCC remains valid!");
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   // Otherwise we create a collection of new RefSCC nodes and build
13390b57cec5SDimitry Andric   // a radix-sort style map from postorder number to these new RefSCCs. We then
13400b57cec5SDimitry Andric   // append SCCs to each of these RefSCCs in the order they occurred in the
13410b57cec5SDimitry Andric   // original SCCs container.
1342bdd1243dSDimitry Andric   for (int I = 0; I < PostOrderNumber; ++I)
13430b57cec5SDimitry Andric     Result.push_back(G->createRefSCC(*G));
13440b57cec5SDimitry Andric 
13450b57cec5SDimitry Andric   // Insert the resulting postorder sequence into the global graph postorder
13460b57cec5SDimitry Andric   // sequence before the current RefSCC in that sequence, and then remove the
13470b57cec5SDimitry Andric   // current one.
13480b57cec5SDimitry Andric   //
13490b57cec5SDimitry Andric   // FIXME: It'd be nice to change the APIs so that we returned an iterator
13500b57cec5SDimitry Andric   // range over the global postorder sequence and generally use that sequence
13510b57cec5SDimitry Andric   // rather than building a separate result vector here.
13520b57cec5SDimitry Andric   int Idx = G->getRefSCCIndex(*this);
13530b57cec5SDimitry Andric   G->PostOrderRefSCCs.erase(G->PostOrderRefSCCs.begin() + Idx);
13540b57cec5SDimitry Andric   G->PostOrderRefSCCs.insert(G->PostOrderRefSCCs.begin() + Idx, Result.begin(),
13550b57cec5SDimitry Andric                              Result.end());
1356bdd1243dSDimitry Andric   for (int I : seq<int>(Idx, G->PostOrderRefSCCs.size()))
1357bdd1243dSDimitry Andric     G->RefSCCIndices[G->PostOrderRefSCCs[I]] = I;
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   for (SCC *C : SCCs) {
13600b57cec5SDimitry Andric     // We store the SCC number in the node's low-link field above.
13610b57cec5SDimitry Andric     int SCCNumber = C->begin()->LowLink;
1362bdd1243dSDimitry Andric     // Clear out all the SCC's node's low-link fields now that we're done
13630b57cec5SDimitry Andric     // using them as side-storage.
13640b57cec5SDimitry Andric     for (Node &N : *C) {
13650b57cec5SDimitry Andric       assert(N.LowLink == SCCNumber &&
13660b57cec5SDimitry Andric              "Cannot have different numbers for nodes in the same SCC!");
13670b57cec5SDimitry Andric       N.LowLink = -1;
13680b57cec5SDimitry Andric     }
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric     RefSCC &RC = *Result[SCCNumber];
13710b57cec5SDimitry Andric     int SCCIndex = RC.SCCs.size();
13720b57cec5SDimitry Andric     RC.SCCs.push_back(C);
13730b57cec5SDimitry Andric     RC.SCCIndices[C] = SCCIndex;
13740b57cec5SDimitry Andric     C->OuterRefSCC = &RC;
13750b57cec5SDimitry Andric   }
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric   // Now that we've moved things into the new RefSCCs, clear out our current
13780b57cec5SDimitry Andric   // one.
13790b57cec5SDimitry Andric   G = nullptr;
13800b57cec5SDimitry Andric   SCCs.clear();
13810b57cec5SDimitry Andric   SCCIndices.clear();
13820b57cec5SDimitry Andric 
1383fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
13840b57cec5SDimitry Andric   // Verify the new RefSCCs we've built.
13850b57cec5SDimitry Andric   for (RefSCC *RC : Result)
13860b57cec5SDimitry Andric     RC->verify();
13870b57cec5SDimitry Andric #endif
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   // Return the new list of SCCs.
13900b57cec5SDimitry Andric   return Result;
13910b57cec5SDimitry Andric }
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric void LazyCallGraph::RefSCC::insertTrivialCallEdge(Node &SourceN,
13940b57cec5SDimitry Andric                                                   Node &TargetN) {
1395fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
13960b57cec5SDimitry Andric   auto ExitVerifier = make_scope_exit([this] { verify(); });
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric   // Check that we aren't breaking some invariants of the SCC graph. Note that
13990b57cec5SDimitry Andric   // this is quadratic in the number of edges in the call graph!
14000b57cec5SDimitry Andric   SCC &SourceC = *G->lookupSCC(SourceN);
14010b57cec5SDimitry Andric   SCC &TargetC = *G->lookupSCC(TargetN);
14020b57cec5SDimitry Andric   if (&SourceC != &TargetC)
14030b57cec5SDimitry Andric     assert(SourceC.isAncestorOf(TargetC) &&
14040b57cec5SDimitry Andric            "Call edge is not trivial in the SCC graph!");
1405fe6060f1SDimitry Andric #endif
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric   // First insert it into the source or find the existing edge.
1408bdd1243dSDimitry Andric   auto [Iterator, Inserted] =
1409bdd1243dSDimitry Andric       SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.size());
1410bdd1243dSDimitry Andric   if (!Inserted) {
14110b57cec5SDimitry Andric     // Already an edge, just update it.
1412bdd1243dSDimitry Andric     Edge &E = SourceN->Edges[Iterator->second];
14130b57cec5SDimitry Andric     if (E.isCall())
14140b57cec5SDimitry Andric       return; // Nothing to do!
14150b57cec5SDimitry Andric     E.setKind(Edge::Call);
14160b57cec5SDimitry Andric   } else {
14170b57cec5SDimitry Andric     // Create the new edge.
14180b57cec5SDimitry Andric     SourceN->Edges.emplace_back(TargetN, Edge::Call);
14190b57cec5SDimitry Andric   }
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric 
14220b57cec5SDimitry Andric void LazyCallGraph::RefSCC::insertTrivialRefEdge(Node &SourceN, Node &TargetN) {
1423fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
14240b57cec5SDimitry Andric   auto ExitVerifier = make_scope_exit([this] { verify(); });
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric   // Check that we aren't breaking some invariants of the RefSCC graph.
14270b57cec5SDimitry Andric   RefSCC &SourceRC = *G->lookupRefSCC(SourceN);
14280b57cec5SDimitry Andric   RefSCC &TargetRC = *G->lookupRefSCC(TargetN);
14290b57cec5SDimitry Andric   if (&SourceRC != &TargetRC)
14300b57cec5SDimitry Andric     assert(SourceRC.isAncestorOf(TargetRC) &&
14310b57cec5SDimitry Andric            "Ref edge is not trivial in the RefSCC graph!");
1432fe6060f1SDimitry Andric #endif
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric   // First insert it into the source or find the existing edge.
1435bdd1243dSDimitry Andric   auto [Iterator, Inserted] =
1436bdd1243dSDimitry Andric       SourceN->EdgeIndexMap.try_emplace(&TargetN, SourceN->Edges.size());
1437bdd1243dSDimitry Andric   (void)Iterator;
1438bdd1243dSDimitry Andric   if (!Inserted)
14390b57cec5SDimitry Andric     // Already an edge, we're done.
14400b57cec5SDimitry Andric     return;
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric   // Create the new edge.
14430b57cec5SDimitry Andric   SourceN->Edges.emplace_back(TargetN, Edge::Ref);
14440b57cec5SDimitry Andric }
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric void LazyCallGraph::RefSCC::replaceNodeFunction(Node &N, Function &NewF) {
14470b57cec5SDimitry Andric   Function &OldF = N.getFunction();
14480b57cec5SDimitry Andric 
1449fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
14500b57cec5SDimitry Andric   auto ExitVerifier = make_scope_exit([this] { verify(); });
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   assert(G->lookupRefSCC(N) == this &&
14530b57cec5SDimitry Andric          "Cannot replace the function of a node outside this RefSCC.");
14540b57cec5SDimitry Andric 
14550b57cec5SDimitry Andric   assert(G->NodeMap.find(&NewF) == G->NodeMap.end() &&
14560b57cec5SDimitry Andric          "Must not have already walked the new function!'");
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   // It is important that this replacement not introduce graph changes so we
14590b57cec5SDimitry Andric   // insist that the caller has already removed every use of the original
14600b57cec5SDimitry Andric   // function and that all uses of the new function correspond to existing
14610b57cec5SDimitry Andric   // edges in the graph. The common and expected way to use this is when
14620b57cec5SDimitry Andric   // replacing the function itself in the IR without changing the call graph
14630b57cec5SDimitry Andric   // shape and just updating the analysis based on that.
14640b57cec5SDimitry Andric   assert(&OldF != &NewF && "Cannot replace a function with itself!");
14650b57cec5SDimitry Andric   assert(OldF.use_empty() &&
14660b57cec5SDimitry Andric          "Must have moved all uses from the old function to the new!");
14670b57cec5SDimitry Andric #endif
14680b57cec5SDimitry Andric 
14690b57cec5SDimitry Andric   N.replaceFunction(NewF);
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric   // Update various call graph maps.
14720b57cec5SDimitry Andric   G->NodeMap.erase(&OldF);
14730b57cec5SDimitry Andric   G->NodeMap[&NewF] = &N;
1474bdd1243dSDimitry Andric 
1475bdd1243dSDimitry Andric   // Update lib functions.
1476bdd1243dSDimitry Andric   if (G->isLibFunction(OldF)) {
1477bdd1243dSDimitry Andric     G->LibFunctions.remove(&OldF);
1478bdd1243dSDimitry Andric     G->LibFunctions.insert(&NewF);
1479bdd1243dSDimitry Andric   }
14800b57cec5SDimitry Andric }
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric void LazyCallGraph::insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK) {
14830b57cec5SDimitry Andric   assert(SCCMap.empty() &&
14840b57cec5SDimitry Andric          "This method cannot be called after SCCs have been formed!");
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric   return SourceN->insertEdgeInternal(TargetN, EK);
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric void LazyCallGraph::removeEdge(Node &SourceN, Node &TargetN) {
14900b57cec5SDimitry Andric   assert(SCCMap.empty() &&
14910b57cec5SDimitry Andric          "This method cannot be called after SCCs have been formed!");
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric   bool Removed = SourceN->removeEdgeInternal(TargetN);
14940b57cec5SDimitry Andric   (void)Removed;
14950b57cec5SDimitry Andric   assert(Removed && "Target not in the edge set for this caller?");
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
1498*0fca6ea1SDimitry Andric void LazyCallGraph::markDeadFunction(Function &F) {
14990b57cec5SDimitry Andric   // FIXME: This is unnecessarily restrictive. We should be able to remove
15000b57cec5SDimitry Andric   // functions which recursively call themselves.
150104eeddc0SDimitry Andric   assert(F.hasZeroLiveUses() &&
15020b57cec5SDimitry Andric          "This routine should only be called on trivially dead functions!");
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric   // We shouldn't remove library functions as they are never really dead while
15050b57cec5SDimitry Andric   // the call graph is in use -- every function definition refers to them.
15060b57cec5SDimitry Andric   assert(!isLibFunction(F) &&
15070b57cec5SDimitry Andric          "Must not remove lib functions from the call graph!");
15080b57cec5SDimitry Andric 
15090b57cec5SDimitry Andric   auto NI = NodeMap.find(&F);
1510*0fca6ea1SDimitry Andric   assert(NI != NodeMap.end() && "Removed function should be known!");
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric   Node &N = *NI->second;
15130b57cec5SDimitry Andric 
1514*0fca6ea1SDimitry Andric   // Remove all call edges out of dead function.
1515*0fca6ea1SDimitry Andric   for (Edge E : *N) {
1516*0fca6ea1SDimitry Andric     if (E.isCall())
1517*0fca6ea1SDimitry Andric       N->setEdgeKind(E.getNode(), Edge::Ref);
1518bdd1243dSDimitry Andric   }
1519bdd1243dSDimitry Andric }
1520bdd1243dSDimitry Andric 
1521*0fca6ea1SDimitry Andric void LazyCallGraph::removeDeadFunctions(ArrayRef<Function *> DeadFs) {
1522*0fca6ea1SDimitry Andric   if (DeadFs.empty())
1523*0fca6ea1SDimitry Andric     return;
1524*0fca6ea1SDimitry Andric 
1525*0fca6ea1SDimitry Andric   // Group dead functions by the RefSCC they're in.
1526*0fca6ea1SDimitry Andric   DenseMap<RefSCC *, SmallVector<Node *, 1>> RCs;
1527*0fca6ea1SDimitry Andric   for (Function *DeadF : DeadFs) {
1528*0fca6ea1SDimitry Andric     Node *N = lookup(*DeadF);
1529*0fca6ea1SDimitry Andric #ifndef NDEBUG
1530*0fca6ea1SDimitry Andric     for (Edge &E : **N) {
1531*0fca6ea1SDimitry Andric       assert(!E.isCall() &&
1532*0fca6ea1SDimitry Andric              "dead function shouldn't have any outgoing call edges");
1533*0fca6ea1SDimitry Andric     }
1534*0fca6ea1SDimitry Andric #endif
1535*0fca6ea1SDimitry Andric     RefSCC *RC = lookupRefSCC(*N);
1536*0fca6ea1SDimitry Andric     RCs[RC].push_back(N);
1537*0fca6ea1SDimitry Andric   }
1538*0fca6ea1SDimitry Andric   // Remove outgoing edges from all dead functions. Dead functions should
1539*0fca6ea1SDimitry Andric   // already have had their call edges removed in markDeadFunction(), so we only
1540*0fca6ea1SDimitry Andric   // need to worry about spurious ref edges.
1541*0fca6ea1SDimitry Andric   for (auto [RC, DeadNs] : RCs) {
1542*0fca6ea1SDimitry Andric     SmallVector<std::pair<Node *, Node *>> InternalEdgesToRemove;
1543*0fca6ea1SDimitry Andric     for (Node *DeadN : DeadNs) {
1544*0fca6ea1SDimitry Andric       for (Edge &E : **DeadN) {
1545*0fca6ea1SDimitry Andric         if (lookupRefSCC(E.getNode()) == RC)
1546*0fca6ea1SDimitry Andric           InternalEdgesToRemove.push_back({DeadN, &E.getNode()});
1547*0fca6ea1SDimitry Andric         else
1548*0fca6ea1SDimitry Andric           RC->removeOutgoingEdge(*DeadN, E.getNode());
1549*0fca6ea1SDimitry Andric       }
1550*0fca6ea1SDimitry Andric     }
1551*0fca6ea1SDimitry Andric     // We ignore the returned RefSCCs since at this point we're done with CGSCC
1552*0fca6ea1SDimitry Andric     // iteration and don't need to add it to any worklists.
1553*0fca6ea1SDimitry Andric     (void)RC->removeInternalRefEdges(InternalEdgesToRemove);
1554*0fca6ea1SDimitry Andric     for (Node *DeadN : DeadNs) {
1555*0fca6ea1SDimitry Andric       RefSCC *DeadRC = lookupRefSCC(*DeadN);
1556*0fca6ea1SDimitry Andric       assert(DeadRC->size() == 1);
1557*0fca6ea1SDimitry Andric       assert(DeadRC->begin()->size() == 1);
1558*0fca6ea1SDimitry Andric       DeadRC->clear();
1559*0fca6ea1SDimitry Andric       DeadRC->G = nullptr;
1560*0fca6ea1SDimitry Andric     }
1561*0fca6ea1SDimitry Andric   }
1562*0fca6ea1SDimitry Andric   // Clean up data structures.
1563*0fca6ea1SDimitry Andric   for (Function *DeadF : DeadFs) {
1564*0fca6ea1SDimitry Andric     Node &N = *lookup(*DeadF);
1565*0fca6ea1SDimitry Andric 
1566bdd1243dSDimitry Andric     EntryEdges.removeEdgeInternal(N);
1567*0fca6ea1SDimitry Andric     SCCMap.erase(SCCMap.find(&N));
1568*0fca6ea1SDimitry Andric     NodeMap.erase(NodeMap.find(DeadF));
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric     N.clear();
15710b57cec5SDimitry Andric     N.G = nullptr;
15720b57cec5SDimitry Andric     N.F = nullptr;
1573*0fca6ea1SDimitry Andric   }
15740b57cec5SDimitry Andric }
15750b57cec5SDimitry Andric 
1576e8d8bef9SDimitry Andric // Gets the Edge::Kind from one function to another by looking at the function's
1577e8d8bef9SDimitry Andric // instructions. Asserts if there is no edge.
1578e8d8bef9SDimitry Andric // Useful for determining what type of edge should exist between functions when
1579e8d8bef9SDimitry Andric // the edge hasn't been created yet.
1580e8d8bef9SDimitry Andric static LazyCallGraph::Edge::Kind getEdgeKind(Function &OriginalFunction,
1581e8d8bef9SDimitry Andric                                              Function &NewFunction) {
1582e8d8bef9SDimitry Andric   // In release builds, assume that if there are no direct calls to the new
1583e8d8bef9SDimitry Andric   // function, then there is a ref edge. In debug builds, keep track of
1584e8d8bef9SDimitry Andric   // references to assert that there is actually a ref edge if there is no call
1585e8d8bef9SDimitry Andric   // edge.
1586e8d8bef9SDimitry Andric #ifndef NDEBUG
1587e8d8bef9SDimitry Andric   SmallVector<Constant *, 16> Worklist;
1588e8d8bef9SDimitry Andric   SmallPtrSet<Constant *, 16> Visited;
1589e8d8bef9SDimitry Andric #endif
1590e8d8bef9SDimitry Andric 
1591e8d8bef9SDimitry Andric   for (Instruction &I : instructions(OriginalFunction)) {
1592e8d8bef9SDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&I)) {
1593e8d8bef9SDimitry Andric       if (Function *Callee = CB->getCalledFunction()) {
1594e8d8bef9SDimitry Andric         if (Callee == &NewFunction)
1595e8d8bef9SDimitry Andric           return LazyCallGraph::Edge::Kind::Call;
1596e8d8bef9SDimitry Andric       }
1597e8d8bef9SDimitry Andric     }
1598e8d8bef9SDimitry Andric #ifndef NDEBUG
1599e8d8bef9SDimitry Andric     for (Value *Op : I.operand_values()) {
1600e8d8bef9SDimitry Andric       if (Constant *C = dyn_cast<Constant>(Op)) {
1601e8d8bef9SDimitry Andric         if (Visited.insert(C).second)
1602e8d8bef9SDimitry Andric           Worklist.push_back(C);
1603e8d8bef9SDimitry Andric       }
1604e8d8bef9SDimitry Andric     }
1605e8d8bef9SDimitry Andric #endif
16065ffd83dbSDimitry Andric   }
16075ffd83dbSDimitry Andric 
1608e8d8bef9SDimitry Andric #ifndef NDEBUG
1609e8d8bef9SDimitry Andric   bool FoundNewFunction = false;
1610e8d8bef9SDimitry Andric   LazyCallGraph::visitReferences(Worklist, Visited, [&](Function &F) {
1611e8d8bef9SDimitry Andric     if (&F == &NewFunction)
1612e8d8bef9SDimitry Andric       FoundNewFunction = true;
1613e8d8bef9SDimitry Andric   });
1614e8d8bef9SDimitry Andric   assert(FoundNewFunction && "No edge from original function to new function");
1615e8d8bef9SDimitry Andric #endif
16165ffd83dbSDimitry Andric 
1617e8d8bef9SDimitry Andric   return LazyCallGraph::Edge::Kind::Ref;
1618e8d8bef9SDimitry Andric }
16195ffd83dbSDimitry Andric 
1620e8d8bef9SDimitry Andric void LazyCallGraph::addSplitFunction(Function &OriginalFunction,
1621e8d8bef9SDimitry Andric                                      Function &NewFunction) {
1622e8d8bef9SDimitry Andric   assert(lookup(OriginalFunction) &&
1623e8d8bef9SDimitry Andric          "Original function's node should already exist");
1624e8d8bef9SDimitry Andric   Node &OriginalN = get(OriginalFunction);
1625e8d8bef9SDimitry Andric   SCC *OriginalC = lookupSCC(OriginalN);
1626e8d8bef9SDimitry Andric   RefSCC *OriginalRC = lookupRefSCC(OriginalN);
1627e8d8bef9SDimitry Andric 
1628fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
1629e8d8bef9SDimitry Andric   OriginalRC->verify();
1630e8d8bef9SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() { OriginalRC->verify(); });
1631e8d8bef9SDimitry Andric #endif
1632e8d8bef9SDimitry Andric 
1633e8d8bef9SDimitry Andric   assert(!lookup(NewFunction) &&
1634e8d8bef9SDimitry Andric          "New function's node should not already exist");
1635e8d8bef9SDimitry Andric   Node &NewN = initNode(NewFunction);
1636e8d8bef9SDimitry Andric 
1637e8d8bef9SDimitry Andric   Edge::Kind EK = getEdgeKind(OriginalFunction, NewFunction);
1638e8d8bef9SDimitry Andric 
1639e8d8bef9SDimitry Andric   SCC *NewC = nullptr;
1640e8d8bef9SDimitry Andric   for (Edge &E : *NewN) {
1641e8d8bef9SDimitry Andric     Node &EN = E.getNode();
1642e8d8bef9SDimitry Andric     if (EK == Edge::Kind::Call && E.isCall() && lookupSCC(EN) == OriginalC) {
1643e8d8bef9SDimitry Andric       // If the edge to the new function is a call edge and there is a call edge
1644e8d8bef9SDimitry Andric       // from the new function to any function in the original function's SCC,
1645e8d8bef9SDimitry Andric       // it is in the same SCC (and RefSCC) as the original function.
1646e8d8bef9SDimitry Andric       NewC = OriginalC;
1647e8d8bef9SDimitry Andric       NewC->Nodes.push_back(&NewN);
1648e8d8bef9SDimitry Andric       break;
1649e8d8bef9SDimitry Andric     }
1650e8d8bef9SDimitry Andric   }
1651e8d8bef9SDimitry Andric 
1652e8d8bef9SDimitry Andric   if (!NewC) {
1653e8d8bef9SDimitry Andric     for (Edge &E : *NewN) {
1654e8d8bef9SDimitry Andric       Node &EN = E.getNode();
1655e8d8bef9SDimitry Andric       if (lookupRefSCC(EN) == OriginalRC) {
1656e8d8bef9SDimitry Andric         // If there is any edge from the new function to any function in the
1657e8d8bef9SDimitry Andric         // original function's RefSCC, it is in the same RefSCC as the original
1658e8d8bef9SDimitry Andric         // function but a new SCC.
1659e8d8bef9SDimitry Andric         RefSCC *NewRC = OriginalRC;
1660e8d8bef9SDimitry Andric         NewC = createSCC(*NewRC, SmallVector<Node *, 1>({&NewN}));
1661e8d8bef9SDimitry Andric 
1662e8d8bef9SDimitry Andric         // The new function's SCC is not the same as the original function's
1663e8d8bef9SDimitry Andric         // SCC, since that case was handled earlier. If the edge from the
1664e8d8bef9SDimitry Andric         // original function to the new function was a call edge, then we need
1665e8d8bef9SDimitry Andric         // to insert the newly created function's SCC before the original
1666bdd1243dSDimitry Andric         // function's SCC. Otherwise, either the new SCC comes after the
1667bdd1243dSDimitry Andric         // original function's SCC, or it doesn't matter, and in both cases we
1668bdd1243dSDimitry Andric         // can add it to the very end.
1669e8d8bef9SDimitry Andric         int InsertIndex = EK == Edge::Kind::Call ? NewRC->SCCIndices[OriginalC]
1670e8d8bef9SDimitry Andric                                                  : NewRC->SCCIndices.size();
1671e8d8bef9SDimitry Andric         NewRC->SCCs.insert(NewRC->SCCs.begin() + InsertIndex, NewC);
1672e8d8bef9SDimitry Andric         for (int I = InsertIndex, Size = NewRC->SCCs.size(); I < Size; ++I)
1673e8d8bef9SDimitry Andric           NewRC->SCCIndices[NewRC->SCCs[I]] = I;
1674e8d8bef9SDimitry Andric 
1675e8d8bef9SDimitry Andric         break;
1676e8d8bef9SDimitry Andric       }
1677e8d8bef9SDimitry Andric     }
1678e8d8bef9SDimitry Andric   }
1679e8d8bef9SDimitry Andric 
1680e8d8bef9SDimitry Andric   if (!NewC) {
1681e8d8bef9SDimitry Andric     // We didn't find any edges back to the original function's RefSCC, so the
1682e8d8bef9SDimitry Andric     // new function belongs in a new RefSCC. The new RefSCC goes before the
1683e8d8bef9SDimitry Andric     // original function's RefSCC.
1684e8d8bef9SDimitry Andric     RefSCC *NewRC = createRefSCC(*this);
1685e8d8bef9SDimitry Andric     NewC = createSCC(*NewRC, SmallVector<Node *, 1>({&NewN}));
1686e8d8bef9SDimitry Andric     NewRC->SCCIndices[NewC] = 0;
1687e8d8bef9SDimitry Andric     NewRC->SCCs.push_back(NewC);
1688e8d8bef9SDimitry Andric     auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1689e8d8bef9SDimitry Andric     PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1690e8d8bef9SDimitry Andric     for (int I = OriginalRCIndex, Size = PostOrderRefSCCs.size(); I < Size; ++I)
1691e8d8bef9SDimitry Andric       RefSCCIndices[PostOrderRefSCCs[I]] = I;
1692e8d8bef9SDimitry Andric   }
1693e8d8bef9SDimitry Andric 
1694e8d8bef9SDimitry Andric   SCCMap[&NewN] = NewC;
1695e8d8bef9SDimitry Andric 
1696e8d8bef9SDimitry Andric   OriginalN->insertEdgeInternal(NewN, EK);
1697e8d8bef9SDimitry Andric }
1698e8d8bef9SDimitry Andric 
1699e8d8bef9SDimitry Andric void LazyCallGraph::addSplitRefRecursiveFunctions(
1700e8d8bef9SDimitry Andric     Function &OriginalFunction, ArrayRef<Function *> NewFunctions) {
1701e8d8bef9SDimitry Andric   assert(!NewFunctions.empty() && "Can't add zero functions");
1702e8d8bef9SDimitry Andric   assert(lookup(OriginalFunction) &&
1703e8d8bef9SDimitry Andric          "Original function's node should already exist");
1704e8d8bef9SDimitry Andric   Node &OriginalN = get(OriginalFunction);
1705e8d8bef9SDimitry Andric   RefSCC *OriginalRC = lookupRefSCC(OriginalN);
1706e8d8bef9SDimitry Andric 
1707fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
1708e8d8bef9SDimitry Andric   OriginalRC->verify();
1709e8d8bef9SDimitry Andric   auto VerifyOnExit = make_scope_exit([&]() {
1710e8d8bef9SDimitry Andric     OriginalRC->verify();
1711e8d8bef9SDimitry Andric     for (Function *NewFunction : NewFunctions)
1712e8d8bef9SDimitry Andric       lookupRefSCC(get(*NewFunction))->verify();
1713e8d8bef9SDimitry Andric   });
1714e8d8bef9SDimitry Andric #endif
1715e8d8bef9SDimitry Andric 
1716e8d8bef9SDimitry Andric   bool ExistsRefToOriginalRefSCC = false;
1717e8d8bef9SDimitry Andric 
1718e8d8bef9SDimitry Andric   for (Function *NewFunction : NewFunctions) {
1719e8d8bef9SDimitry Andric     Node &NewN = initNode(*NewFunction);
1720e8d8bef9SDimitry Andric 
1721e8d8bef9SDimitry Andric     OriginalN->insertEdgeInternal(NewN, Edge::Kind::Ref);
1722e8d8bef9SDimitry Andric 
1723e8d8bef9SDimitry Andric     // Check if there is any edge from any new function back to any function in
1724e8d8bef9SDimitry Andric     // the original function's RefSCC.
1725e8d8bef9SDimitry Andric     for (Edge &E : *NewN) {
1726e8d8bef9SDimitry Andric       if (lookupRefSCC(E.getNode()) == OriginalRC) {
1727e8d8bef9SDimitry Andric         ExistsRefToOriginalRefSCC = true;
1728e8d8bef9SDimitry Andric         break;
1729e8d8bef9SDimitry Andric       }
1730e8d8bef9SDimitry Andric     }
1731e8d8bef9SDimitry Andric   }
1732e8d8bef9SDimitry Andric 
1733e8d8bef9SDimitry Andric   RefSCC *NewRC;
1734e8d8bef9SDimitry Andric   if (ExistsRefToOriginalRefSCC) {
1735e8d8bef9SDimitry Andric     // If there is any edge from any new function to any function in the
1736e8d8bef9SDimitry Andric     // original function's RefSCC, all new functions will be in the same RefSCC
1737e8d8bef9SDimitry Andric     // as the original function.
1738e8d8bef9SDimitry Andric     NewRC = OriginalRC;
1739e8d8bef9SDimitry Andric   } else {
1740e8d8bef9SDimitry Andric     // Otherwise the new functions are in their own RefSCC.
1741e8d8bef9SDimitry Andric     NewRC = createRefSCC(*this);
1742e8d8bef9SDimitry Andric     // The new RefSCC goes before the original function's RefSCC in postorder
1743e8d8bef9SDimitry Andric     // since there are only edges from the original function's RefSCC to the new
1744e8d8bef9SDimitry Andric     // RefSCC.
1745e8d8bef9SDimitry Andric     auto OriginalRCIndex = RefSCCIndices.find(OriginalRC)->second;
1746e8d8bef9SDimitry Andric     PostOrderRefSCCs.insert(PostOrderRefSCCs.begin() + OriginalRCIndex, NewRC);
1747e8d8bef9SDimitry Andric     for (int I = OriginalRCIndex, Size = PostOrderRefSCCs.size(); I < Size; ++I)
1748e8d8bef9SDimitry Andric       RefSCCIndices[PostOrderRefSCCs[I]] = I;
1749e8d8bef9SDimitry Andric   }
1750e8d8bef9SDimitry Andric 
1751e8d8bef9SDimitry Andric   for (Function *NewFunction : NewFunctions) {
1752e8d8bef9SDimitry Andric     Node &NewN = get(*NewFunction);
1753e8d8bef9SDimitry Andric     // Each new function is in its own new SCC. The original function can only
1754e8d8bef9SDimitry Andric     // have a ref edge to new functions, and no other existing functions can
1755e8d8bef9SDimitry Andric     // have references to new functions. Each new function only has a ref edge
1756e8d8bef9SDimitry Andric     // to the other new functions.
1757e8d8bef9SDimitry Andric     SCC *NewC = createSCC(*NewRC, SmallVector<Node *, 1>({&NewN}));
1758e8d8bef9SDimitry Andric     // The new SCCs are either sibling SCCs or parent SCCs to all other existing
1759e8d8bef9SDimitry Andric     // SCCs in the RefSCC. Either way, they can go at the back of the postorder
1760e8d8bef9SDimitry Andric     // SCC list.
1761e8d8bef9SDimitry Andric     auto Index = NewRC->SCCIndices.size();
1762e8d8bef9SDimitry Andric     NewRC->SCCIndices[NewC] = Index;
1763e8d8bef9SDimitry Andric     NewRC->SCCs.push_back(NewC);
1764e8d8bef9SDimitry Andric     SCCMap[&NewN] = NewC;
1765e8d8bef9SDimitry Andric   }
1766e8d8bef9SDimitry Andric 
1767e8d8bef9SDimitry Andric #ifndef NDEBUG
1768e8d8bef9SDimitry Andric   for (Function *F1 : NewFunctions) {
1769e8d8bef9SDimitry Andric     assert(getEdgeKind(OriginalFunction, *F1) == Edge::Kind::Ref &&
1770e8d8bef9SDimitry Andric            "Expected ref edges from original function to every new function");
1771e8d8bef9SDimitry Andric     Node &N1 = get(*F1);
1772e8d8bef9SDimitry Andric     for (Function *F2 : NewFunctions) {
1773e8d8bef9SDimitry Andric       if (F1 == F2)
1774e8d8bef9SDimitry Andric         continue;
1775e8d8bef9SDimitry Andric       Node &N2 = get(*F2);
1776e8d8bef9SDimitry Andric       assert(!N1->lookup(N2)->isCall() &&
1777e8d8bef9SDimitry Andric              "Edges between new functions must be ref edges");
1778e8d8bef9SDimitry Andric     }
1779e8d8bef9SDimitry Andric   }
1780e8d8bef9SDimitry Andric #endif
17815ffd83dbSDimitry Andric }
17825ffd83dbSDimitry Andric 
17830b57cec5SDimitry Andric LazyCallGraph::Node &LazyCallGraph::insertInto(Function &F, Node *&MappedN) {
17840b57cec5SDimitry Andric   return *new (MappedN = BPA.Allocate()) Node(*this, F);
17850b57cec5SDimitry Andric }
17860b57cec5SDimitry Andric 
17870b57cec5SDimitry Andric void LazyCallGraph::updateGraphPtrs() {
17880b57cec5SDimitry Andric   // Walk the node map to update their graph pointers. While this iterates in
1789bdd1243dSDimitry Andric   // an unstable order, the order has no effect, so it remains correct.
17900b57cec5SDimitry Andric   for (auto &FunctionNodePair : NodeMap)
17910b57cec5SDimitry Andric     FunctionNodePair.second->G = this;
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric   for (auto *RC : PostOrderRefSCCs)
17940b57cec5SDimitry Andric     RC->G = this;
17950b57cec5SDimitry Andric }
17960b57cec5SDimitry Andric 
1797e8d8bef9SDimitry Andric LazyCallGraph::Node &LazyCallGraph::initNode(Function &F) {
17985ffd83dbSDimitry Andric   Node &N = get(F);
17995ffd83dbSDimitry Andric   N.DFSNumber = N.LowLink = -1;
18005ffd83dbSDimitry Andric   N.populate();
1801e8d8bef9SDimitry Andric   NodeMap[&F] = &N;
18025ffd83dbSDimitry Andric   return N;
18035ffd83dbSDimitry Andric }
18045ffd83dbSDimitry Andric 
18050b57cec5SDimitry Andric template <typename RootsT, typename GetBeginT, typename GetEndT,
18060b57cec5SDimitry Andric           typename GetNodeT, typename FormSCCCallbackT>
18070b57cec5SDimitry Andric void LazyCallGraph::buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
18080b57cec5SDimitry Andric                                      GetEndT &&GetEnd, GetNodeT &&GetNode,
18090b57cec5SDimitry Andric                                      FormSCCCallbackT &&FormSCC) {
18100b57cec5SDimitry Andric   using EdgeItT = decltype(GetBegin(std::declval<Node &>()));
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric   SmallVector<std::pair<Node *, EdgeItT>, 16> DFSStack;
18130b57cec5SDimitry Andric   SmallVector<Node *, 16> PendingSCCStack;
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric   // Scan down the stack and DFS across the call edges.
18160b57cec5SDimitry Andric   for (Node *RootN : Roots) {
18170b57cec5SDimitry Andric     assert(DFSStack.empty() &&
18180b57cec5SDimitry Andric            "Cannot begin a new root with a non-empty DFS stack!");
18190b57cec5SDimitry Andric     assert(PendingSCCStack.empty() &&
18200b57cec5SDimitry Andric            "Cannot begin a new root with pending nodes for an SCC!");
18210b57cec5SDimitry Andric 
18220b57cec5SDimitry Andric     // Skip any nodes we've already reached in the DFS.
18230b57cec5SDimitry Andric     if (RootN->DFSNumber != 0) {
18240b57cec5SDimitry Andric       assert(RootN->DFSNumber == -1 &&
18250b57cec5SDimitry Andric              "Shouldn't have any mid-DFS root nodes!");
18260b57cec5SDimitry Andric       continue;
18270b57cec5SDimitry Andric     }
18280b57cec5SDimitry Andric 
18290b57cec5SDimitry Andric     RootN->DFSNumber = RootN->LowLink = 1;
18300b57cec5SDimitry Andric     int NextDFSNumber = 2;
18310b57cec5SDimitry Andric 
1832bdd1243dSDimitry Andric     DFSStack.emplace_back(RootN, GetBegin(*RootN));
18330b57cec5SDimitry Andric     do {
1834bdd1243dSDimitry Andric       auto [N, I] = DFSStack.pop_back_val();
18350b57cec5SDimitry Andric       auto E = GetEnd(*N);
18360b57cec5SDimitry Andric       while (I != E) {
18370b57cec5SDimitry Andric         Node &ChildN = GetNode(I);
18380b57cec5SDimitry Andric         if (ChildN.DFSNumber == 0) {
18390b57cec5SDimitry Andric           // We haven't yet visited this child, so descend, pushing the current
18400b57cec5SDimitry Andric           // node onto the stack.
1841bdd1243dSDimitry Andric           DFSStack.emplace_back(N, I);
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric           ChildN.DFSNumber = ChildN.LowLink = NextDFSNumber++;
18440b57cec5SDimitry Andric           N = &ChildN;
18450b57cec5SDimitry Andric           I = GetBegin(*N);
18460b57cec5SDimitry Andric           E = GetEnd(*N);
18470b57cec5SDimitry Andric           continue;
18480b57cec5SDimitry Andric         }
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric         // If the child has already been added to some child component, it
18510b57cec5SDimitry Andric         // couldn't impact the low-link of this parent because it isn't
18520b57cec5SDimitry Andric         // connected, and thus its low-link isn't relevant so skip it.
18530b57cec5SDimitry Andric         if (ChildN.DFSNumber == -1) {
18540b57cec5SDimitry Andric           ++I;
18550b57cec5SDimitry Andric           continue;
18560b57cec5SDimitry Andric         }
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric         // Track the lowest linked child as the lowest link for this node.
18590b57cec5SDimitry Andric         assert(ChildN.LowLink > 0 && "Must have a positive low-link number!");
18600b57cec5SDimitry Andric         if (ChildN.LowLink < N->LowLink)
18610b57cec5SDimitry Andric           N->LowLink = ChildN.LowLink;
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric         // Move to the next edge.
18640b57cec5SDimitry Andric         ++I;
18650b57cec5SDimitry Andric       }
18660b57cec5SDimitry Andric 
18670b57cec5SDimitry Andric       // We've finished processing N and its descendants, put it on our pending
18680b57cec5SDimitry Andric       // SCC stack to eventually get merged into an SCC of nodes.
18690b57cec5SDimitry Andric       PendingSCCStack.push_back(N);
18700b57cec5SDimitry Andric 
18710b57cec5SDimitry Andric       // If this node is linked to some lower entry, continue walking up the
18720b57cec5SDimitry Andric       // stack.
18730b57cec5SDimitry Andric       if (N->LowLink != N->DFSNumber)
18740b57cec5SDimitry Andric         continue;
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric       // Otherwise, we've completed an SCC. Append it to our post order list of
18770b57cec5SDimitry Andric       // SCCs.
18780b57cec5SDimitry Andric       int RootDFSNumber = N->DFSNumber;
18790b57cec5SDimitry Andric       // Find the range of the node stack by walking down until we pass the
18800b57cec5SDimitry Andric       // root DFS number.
18810b57cec5SDimitry Andric       auto SCCNodes = make_range(
18820b57cec5SDimitry Andric           PendingSCCStack.rbegin(),
18830b57cec5SDimitry Andric           find_if(reverse(PendingSCCStack), [RootDFSNumber](const Node *N) {
18840b57cec5SDimitry Andric             return N->DFSNumber < RootDFSNumber;
18850b57cec5SDimitry Andric           }));
18860b57cec5SDimitry Andric       // Form a new SCC out of these nodes and then clear them off our pending
18870b57cec5SDimitry Andric       // stack.
18880b57cec5SDimitry Andric       FormSCC(SCCNodes);
18890b57cec5SDimitry Andric       PendingSCCStack.erase(SCCNodes.end().base(), PendingSCCStack.end());
18900b57cec5SDimitry Andric     } while (!DFSStack.empty());
18910b57cec5SDimitry Andric   }
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric /// Build the internal SCCs for a RefSCC from a sequence of nodes.
18950b57cec5SDimitry Andric ///
18960b57cec5SDimitry Andric /// Appends the SCCs to the provided vector and updates the map with their
18970b57cec5SDimitry Andric /// indices. Both the vector and map must be empty when passed into this
18980b57cec5SDimitry Andric /// routine.
18990b57cec5SDimitry Andric void LazyCallGraph::buildSCCs(RefSCC &RC, node_stack_range Nodes) {
19000b57cec5SDimitry Andric   assert(RC.SCCs.empty() && "Already built SCCs!");
19010b57cec5SDimitry Andric   assert(RC.SCCIndices.empty() && "Already mapped SCC indices!");
19020b57cec5SDimitry Andric 
19030b57cec5SDimitry Andric   for (Node *N : Nodes) {
19040b57cec5SDimitry Andric     assert(N->LowLink >= (*Nodes.begin())->LowLink &&
19050b57cec5SDimitry Andric            "We cannot have a low link in an SCC lower than its root on the "
19060b57cec5SDimitry Andric            "stack!");
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric     // This node will go into the next RefSCC, clear out its DFS and low link
19090b57cec5SDimitry Andric     // as we scan.
19100b57cec5SDimitry Andric     N->DFSNumber = N->LowLink = 0;
19110b57cec5SDimitry Andric   }
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   // Each RefSCC contains a DAG of the call SCCs. To build these, we do
19140b57cec5SDimitry Andric   // a direct walk of the call edges using Tarjan's algorithm. We reuse the
19150b57cec5SDimitry Andric   // internal storage as we won't need it for the outer graph's DFS any longer.
19160b57cec5SDimitry Andric   buildGenericSCCs(
19170b57cec5SDimitry Andric       Nodes, [](Node &N) { return N->call_begin(); },
19180b57cec5SDimitry Andric       [](Node &N) { return N->call_end(); },
19190b57cec5SDimitry Andric       [](EdgeSequence::call_iterator I) -> Node & { return I->getNode(); },
19200b57cec5SDimitry Andric       [this, &RC](node_stack_range Nodes) {
19210b57cec5SDimitry Andric         RC.SCCs.push_back(createSCC(RC, Nodes));
19220b57cec5SDimitry Andric         for (Node &N : *RC.SCCs.back()) {
19230b57cec5SDimitry Andric           N.DFSNumber = N.LowLink = -1;
19240b57cec5SDimitry Andric           SCCMap[&N] = RC.SCCs.back();
19250b57cec5SDimitry Andric         }
19260b57cec5SDimitry Andric       });
19270b57cec5SDimitry Andric 
19280b57cec5SDimitry Andric   // Wire up the SCC indices.
1929bdd1243dSDimitry Andric   for (int I = 0, Size = RC.SCCs.size(); I < Size; ++I)
1930bdd1243dSDimitry Andric     RC.SCCIndices[RC.SCCs[I]] = I;
19310b57cec5SDimitry Andric }
19320b57cec5SDimitry Andric 
19330b57cec5SDimitry Andric void LazyCallGraph::buildRefSCCs() {
19340b57cec5SDimitry Andric   if (EntryEdges.empty() || !PostOrderRefSCCs.empty())
19350b57cec5SDimitry Andric     // RefSCCs are either non-existent or already built!
19360b57cec5SDimitry Andric     return;
19370b57cec5SDimitry Andric 
19380b57cec5SDimitry Andric   assert(RefSCCIndices.empty() && "Already mapped RefSCC indices!");
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   SmallVector<Node *, 16> Roots;
19410b57cec5SDimitry Andric   for (Edge &E : *this)
19420b57cec5SDimitry Andric     Roots.push_back(&E.getNode());
19430b57cec5SDimitry Andric 
1944e8d8bef9SDimitry Andric   // The roots will be iterated in order.
19450b57cec5SDimitry Andric   buildGenericSCCs(
19460b57cec5SDimitry Andric       Roots,
19470b57cec5SDimitry Andric       [](Node &N) {
19480b57cec5SDimitry Andric         // We need to populate each node as we begin to walk its edges.
19490b57cec5SDimitry Andric         N.populate();
19500b57cec5SDimitry Andric         return N->begin();
19510b57cec5SDimitry Andric       },
19520b57cec5SDimitry Andric       [](Node &N) { return N->end(); },
19530b57cec5SDimitry Andric       [](EdgeSequence::iterator I) -> Node & { return I->getNode(); },
19540b57cec5SDimitry Andric       [this](node_stack_range Nodes) {
19550b57cec5SDimitry Andric         RefSCC *NewRC = createRefSCC(*this);
19560b57cec5SDimitry Andric         buildSCCs(*NewRC, Nodes);
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric         // Push the new node into the postorder list and remember its position
19590b57cec5SDimitry Andric         // in the index map.
19600b57cec5SDimitry Andric         bool Inserted =
1961bdd1243dSDimitry Andric             RefSCCIndices.try_emplace(NewRC, PostOrderRefSCCs.size()).second;
19620b57cec5SDimitry Andric         (void)Inserted;
19630b57cec5SDimitry Andric         assert(Inserted && "Cannot already have this RefSCC in the index map!");
19640b57cec5SDimitry Andric         PostOrderRefSCCs.push_back(NewRC);
1965fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS
19660b57cec5SDimitry Andric         NewRC->verify();
19670b57cec5SDimitry Andric #endif
19680b57cec5SDimitry Andric       });
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
1971349cc55cSDimitry Andric void LazyCallGraph::visitReferences(SmallVectorImpl<Constant *> &Worklist,
1972349cc55cSDimitry Andric                                     SmallPtrSetImpl<Constant *> &Visited,
1973349cc55cSDimitry Andric                                     function_ref<void(Function &)> Callback) {
1974349cc55cSDimitry Andric   while (!Worklist.empty()) {
1975349cc55cSDimitry Andric     Constant *C = Worklist.pop_back_val();
1976349cc55cSDimitry Andric 
1977349cc55cSDimitry Andric     if (Function *F = dyn_cast<Function>(C)) {
1978349cc55cSDimitry Andric       if (!F->isDeclaration())
1979349cc55cSDimitry Andric         Callback(*F);
1980349cc55cSDimitry Andric       continue;
1981349cc55cSDimitry Andric     }
1982349cc55cSDimitry Andric 
1983349cc55cSDimitry Andric     // blockaddresses are weird and don't participate in the call graph anyway,
1984349cc55cSDimitry Andric     // skip them.
1985349cc55cSDimitry Andric     if (isa<BlockAddress>(C))
1986349cc55cSDimitry Andric       continue;
1987349cc55cSDimitry Andric 
1988349cc55cSDimitry Andric     for (Value *Op : C->operand_values())
1989349cc55cSDimitry Andric       if (Visited.insert(cast<Constant>(Op)).second)
1990349cc55cSDimitry Andric         Worklist.push_back(cast<Constant>(Op));
1991349cc55cSDimitry Andric   }
1992349cc55cSDimitry Andric }
1993349cc55cSDimitry Andric 
19940b57cec5SDimitry Andric AnalysisKey LazyCallGraphAnalysis::Key;
19950b57cec5SDimitry Andric 
19960b57cec5SDimitry Andric LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
19970b57cec5SDimitry Andric 
19980b57cec5SDimitry Andric static void printNode(raw_ostream &OS, LazyCallGraph::Node &N) {
19990b57cec5SDimitry Andric   OS << "  Edges in function: " << N.getFunction().getName() << "\n";
20000b57cec5SDimitry Andric   for (LazyCallGraph::Edge &E : N.populate())
20010b57cec5SDimitry Andric     OS << "    " << (E.isCall() ? "call" : "ref ") << " -> "
20020b57cec5SDimitry Andric        << E.getFunction().getName() << "\n";
20030b57cec5SDimitry Andric 
20040b57cec5SDimitry Andric   OS << "\n";
20050b57cec5SDimitry Andric }
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric static void printSCC(raw_ostream &OS, LazyCallGraph::SCC &C) {
20088bcb0991SDimitry Andric   OS << "    SCC with " << C.size() << " functions:\n";
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric   for (LazyCallGraph::Node &N : C)
20110b57cec5SDimitry Andric     OS << "      " << N.getFunction().getName() << "\n";
20120b57cec5SDimitry Andric }
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric static void printRefSCC(raw_ostream &OS, LazyCallGraph::RefSCC &C) {
20158bcb0991SDimitry Andric   OS << "  RefSCC with " << C.size() << " call SCCs:\n";
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   for (LazyCallGraph::SCC &InnerC : C)
20180b57cec5SDimitry Andric     printSCC(OS, InnerC);
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   OS << "\n";
20210b57cec5SDimitry Andric }
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric PreservedAnalyses LazyCallGraphPrinterPass::run(Module &M,
20240b57cec5SDimitry Andric                                                 ModuleAnalysisManager &AM) {
20250b57cec5SDimitry Andric   LazyCallGraph &G = AM.getResult<LazyCallGraphAnalysis>(M);
20260b57cec5SDimitry Andric 
20270b57cec5SDimitry Andric   OS << "Printing the call graph for module: " << M.getModuleIdentifier()
20280b57cec5SDimitry Andric      << "\n\n";
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   for (Function &F : M)
20310b57cec5SDimitry Andric     printNode(OS, G.get(F));
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric   G.buildRefSCCs();
20340b57cec5SDimitry Andric   for (LazyCallGraph::RefSCC &C : G.postorder_ref_sccs())
20350b57cec5SDimitry Andric     printRefSCC(OS, C);
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric   return PreservedAnalyses::all();
20380b57cec5SDimitry Andric }
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric LazyCallGraphDOTPrinterPass::LazyCallGraphDOTPrinterPass(raw_ostream &OS)
20410b57cec5SDimitry Andric     : OS(OS) {}
20420b57cec5SDimitry Andric 
20430b57cec5SDimitry Andric static void printNodeDOT(raw_ostream &OS, LazyCallGraph::Node &N) {
20445ffd83dbSDimitry Andric   std::string Name =
20455ffd83dbSDimitry Andric       "\"" + DOT::EscapeString(std::string(N.getFunction().getName())) + "\"";
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric   for (LazyCallGraph::Edge &E : N.populate()) {
20480b57cec5SDimitry Andric     OS << "  " << Name << " -> \""
20495ffd83dbSDimitry Andric        << DOT::EscapeString(std::string(E.getFunction().getName())) << "\"";
20500b57cec5SDimitry Andric     if (!E.isCall()) // It is a ref edge.
20510b57cec5SDimitry Andric       OS << " [style=dashed,label=\"ref\"]";
20520b57cec5SDimitry Andric     OS << ";\n";
20530b57cec5SDimitry Andric   }
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric   OS << "\n";
20560b57cec5SDimitry Andric }
20570b57cec5SDimitry Andric 
20580b57cec5SDimitry Andric PreservedAnalyses LazyCallGraphDOTPrinterPass::run(Module &M,
20590b57cec5SDimitry Andric                                                    ModuleAnalysisManager &AM) {
20600b57cec5SDimitry Andric   LazyCallGraph &G = AM.getResult<LazyCallGraphAnalysis>(M);
20610b57cec5SDimitry Andric 
20620b57cec5SDimitry Andric   OS << "digraph \"" << DOT::EscapeString(M.getModuleIdentifier()) << "\" {\n";
20630b57cec5SDimitry Andric 
20640b57cec5SDimitry Andric   for (Function &F : M)
20650b57cec5SDimitry Andric     printNodeDOT(OS, G.get(F));
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   OS << "}\n";
20680b57cec5SDimitry Andric 
20690b57cec5SDimitry Andric   return PreservedAnalyses::all();
20700b57cec5SDimitry Andric }
2071