summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/LazyCallGraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/LazyCallGraph.cpp')
-rw-r--r--llvm/lib/Analysis/LazyCallGraph.cpp293
1 files changed, 160 insertions, 133 deletions
diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp
index 0f0f31e62ac..11e1166001a 100644
--- a/llvm/lib/Analysis/LazyCallGraph.cpp
+++ b/llvm/lib/Analysis/LazyCallGraph.cpp
@@ -20,30 +20,36 @@ using namespace llvm;
#define DEBUG_TYPE "lcg"
-static void findCallees(
- SmallVectorImpl<Constant *> &Worklist, SmallPtrSetImpl<Constant *> &Visited,
- SmallVectorImpl<PointerUnion<Function *, LazyCallGraph::Node *>> &Callees,
- DenseMap<Function *, size_t> &CalleeIndexMap) {
+static void addEdge(SmallVectorImpl<LazyCallGraph::Edge> &Edges,
+ DenseMap<Function *, size_t> &EdgeIndexMap, Function &F,
+ LazyCallGraph::Edge::Kind EK) {
+ // Note that we consider *any* function with a definition to be a viable
+ // edge. Even if the function's definition is subject to replacement by
+ // some other module (say, a weak definition) there may still be
+ // optimizations which essentially speculate based on the definition and
+ // a way to check that the specific definition is in fact the one being
+ // used. For example, this could be done by moving the weak definition to
+ // a strong (internal) definition and making the weak definition be an
+ // alias. Then a test of the address of the weak function against the new
+ // strong definition's address would be an effective way to determine the
+ // safety of optimizing a direct call edge.
+ if (!F.isDeclaration() &&
+ EdgeIndexMap.insert(std::make_pair(&F, Edges.size())).second) {
+ DEBUG(dbgs() << " Added callable function: " << F.getName() << "\n");
+ Edges.emplace_back(LazyCallGraph::Edge(F, EK));
+ }
+}
+
+static void findReferences(
+ SmallVectorImpl<Constant *> &Worklist,
+ SmallPtrSetImpl<Constant *> &Visited,
+ SmallVectorImpl<LazyCallGraph::Edge> &Edges,
+ DenseMap<Function *, size_t> &EdgeIndexMap) {
while (!Worklist.empty()) {
Constant *C = Worklist.pop_back_val();
if (Function *F = dyn_cast<Function>(C)) {
- // Note that we consider *any* function with a definition to be a viable
- // edge. Even if the function's definition is subject to replacement by
- // some other module (say, a weak definition) there may still be
- // optimizations which essentially speculate based on the definition and
- // a way to check that the specific definition is in fact the one being
- // used. For example, this could be done by moving the weak definition to
- // a strong (internal) definition and making the weak definition be an
- // alias. Then a test of the address of the weak function against the new
- // strong definition's address would be an effective way to determine the
- // safety of optimizing a direct call edge.
- if (!F->isDeclaration() &&
- CalleeIndexMap.insert(std::make_pair(F, Callees.size())).second) {
- DEBUG(dbgs() << " Added callable function: " << F->getName()
- << "\n");
- Callees.push_back(F);
- }
+ addEdge(Edges, EdgeIndexMap, *F, LazyCallGraph::Edge::Ref);
continue;
}
@@ -59,42 +65,55 @@ LazyCallGraph::Node::Node(LazyCallGraph &G, Function &F)
<< "' to the graph.\n");
SmallVector<Constant *, 16> Worklist;
+ SmallPtrSet<Function *, 4> Callees;
SmallPtrSet<Constant *, 16> Visited;
- // Find all the potential callees in this function. First walk the
- // instructions and add every operand which is a constant to the worklist.
+
+ // Find all the potential call graph edges in this function. We track both
+ // actual call edges and indirect references to functions. The direct calls
+ // are trivially added, but to accumulate the latter we walk the instructions
+ // and add every operand which is a constant to the worklist to process
+ // afterward.
for (BasicBlock &BB : F)
- for (Instruction &I : BB)
+ for (Instruction &I : BB) {
+ if (auto CS = CallSite(&I))
+ if (Function *Callee = CS.getCalledFunction())
+ if (Callees.insert(Callee).second) {
+ Visited.insert(Callee);
+ addEdge(Edges, EdgeIndexMap, *Callee, LazyCallGraph::Edge::Call);
+ }
+
for (Value *Op : I.operand_values())
if (Constant *C = dyn_cast<Constant>(Op))
if (Visited.insert(C).second)
Worklist.push_back(C);
+ }
// We've collected all the constant (and thus potentially function or
// function containing) operands to all of the instructions in the function.
// Process them (recursively) collecting every function found.
- findCallees(Worklist, Visited, Callees, CalleeIndexMap);
+ findReferences(Worklist, Visited, Edges, EdgeIndexMap);
}
-void LazyCallGraph::Node::insertEdgeInternal(Function &Callee) {
- if (Node *N = G->lookup(Callee))
- return insertEdgeInternal(*N);
+void LazyCallGraph::Node::insertEdgeInternal(Function &Child, Edge::Kind EK) {
+ if (Node *N = G->lookup(Child))
+ return insertEdgeInternal(*N, EK);
- CalleeIndexMap.insert(std::make_pair(&Callee, Callees.size()));
- Callees.push_back(&Callee);
+ EdgeIndexMap.insert(std::make_pair(&Child, Edges.size()));
+ Edges.emplace_back(Child, EK);
}
-void LazyCallGraph::Node::insertEdgeInternal(Node &CalleeN) {
- CalleeIndexMap.insert(std::make_pair(&CalleeN.getFunction(), Callees.size()));
- Callees.push_back(&CalleeN);
+void LazyCallGraph::Node::insertEdgeInternal(Node &ChildN, Edge::Kind EK) {
+ EdgeIndexMap.insert(std::make_pair(&ChildN.getFunction(), Edges.size()));
+ Edges.emplace_back(ChildN, EK);
}
-void LazyCallGraph::Node::removeEdgeInternal(Function &Callee) {
- auto IndexMapI = CalleeIndexMap.find(&Callee);
- assert(IndexMapI != CalleeIndexMap.end() &&
- "Callee not in the callee set for this caller?");
+void LazyCallGraph::Node::removeEdgeInternal(Function &Child) {
+ auto IndexMapI = EdgeIndexMap.find(&Child);
+ assert(IndexMapI != EdgeIndexMap.end() &&
+ "Child not in the edge set for this caller?");
- Callees[IndexMapI->second] = nullptr;
- CalleeIndexMap.erase(IndexMapI);
+ Edges[IndexMapI->second] = Edge();
+ EdgeIndexMap.erase(IndexMapI);
}
LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
@@ -102,10 +121,10 @@ LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
<< "\n");
for (Function &F : M)
if (!F.isDeclaration() && !F.hasLocalLinkage())
- if (EntryIndexMap.insert(std::make_pair(&F, EntryNodes.size())).second) {
+ if (EntryIndexMap.insert(std::make_pair(&F, EntryEdges.size())).second) {
DEBUG(dbgs() << " Adding '" << F.getName()
<< "' to entry set of the graph.\n");
- EntryNodes.push_back(&F);
+ EntryEdges.emplace_back(F, Edge::Ref);
}
// Now add entry nodes for functions reachable via initializers to globals.
@@ -118,21 +137,15 @@ LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
DEBUG(dbgs() << " Adding functions referenced by global initializers to the "
"entry set.\n");
- findCallees(Worklist, Visited, EntryNodes, EntryIndexMap);
-
- for (auto &Entry : EntryNodes) {
- assert(!Entry.isNull() &&
- "We can't have removed edges before we finish the constructor!");
- if (Function *F = Entry.dyn_cast<Function *>())
- SCCEntryNodes.push_back(F);
- else
- SCCEntryNodes.push_back(&Entry.get<Node *>()->getFunction());
- }
+ findReferences(Worklist, Visited, EntryEdges, EntryIndexMap);
+
+ for (const Edge &E : EntryEdges)
+ SCCEntryNodes.push_back(&E.getFunction());
}
LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)
: BPA(std::move(G.BPA)), NodeMap(std::move(G.NodeMap)),
- EntryNodes(std::move(G.EntryNodes)),
+ EntryEdges(std::move(G.EntryEdges)),
EntryIndexMap(std::move(G.EntryIndexMap)), SCCBPA(std::move(G.SCCBPA)),
SCCMap(std::move(G.SCCMap)), LeafSCCs(std::move(G.LeafSCCs)),
DFSStack(std::move(G.DFSStack)),
@@ -144,7 +157,7 @@ LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)
LazyCallGraph &LazyCallGraph::operator=(LazyCallGraph &&G) {
BPA = std::move(G.BPA);
NodeMap = std::move(G.NodeMap);
- EntryNodes = std::move(G.EntryNodes);
+ EntryEdges = std::move(G.EntryEdges);
EntryIndexMap = std::move(G.EntryIndexMap);
SCCBPA = std::move(G.SCCBPA);
SCCMap = std::move(G.SCCMap);
@@ -177,43 +190,46 @@ bool LazyCallGraph::SCC::isDescendantOf(const SCC &C) const {
return false;
}
-void LazyCallGraph::SCC::insertIntraSCCEdge(Node &CallerN, Node &CalleeN) {
+void LazyCallGraph::SCC::insertIntraSCCEdge(Node &ParentN, Node &ChildN,
+ Edge::Kind EK) {
// First insert it into the caller.
- CallerN.insertEdgeInternal(CalleeN);
+ ParentN.insertEdgeInternal(ChildN, EK);
- assert(G->SCCMap.lookup(&CallerN) == this && "Caller must be in this SCC.");
- assert(G->SCCMap.lookup(&CalleeN) == this && "Callee must be in this SCC.");
+ assert(G->SCCMap.lookup(&ParentN) == this && "Parent must be in this SCC.");
+ assert(G->SCCMap.lookup(&ChildN) == this && "Child must be in this SCC.");
// Nothing changes about this SCC or any other.
}
-void LazyCallGraph::SCC::insertOutgoingEdge(Node &CallerN, Node &CalleeN) {
+void LazyCallGraph::SCC::insertOutgoingEdge(Node &ParentN, Node &ChildN,
+ Edge::Kind EK) {
// First insert it into the caller.
- CallerN.insertEdgeInternal(CalleeN);
+ ParentN.insertEdgeInternal(ChildN, EK);
- assert(G->SCCMap.lookup(&CallerN) == this && "Caller must be in this SCC.");
+ assert(G->SCCMap.lookup(&ParentN) == this && "Parent must be in this SCC.");
- SCC &CalleeC = *G->SCCMap.lookup(&CalleeN);
- assert(&CalleeC != this && "Callee must not be in this SCC.");
- assert(CalleeC.isDescendantOf(*this) &&
- "Callee must be a descendant of the Caller.");
+ SCC &ChildC = *G->SCCMap.lookup(&ChildN);
+ assert(&ChildC != this && "Child must not be in this SCC.");
+ assert(ChildC.isDescendantOf(*this) &&
+ "Child must be a descendant of the Parent.");
// The only change required is to add this SCC to the parent set of the
// callee.
- CalleeC.ParentSCCs.insert(this);
+ ChildC.ParentSCCs.insert(this);
}
SmallVector<LazyCallGraph::SCC *, 1>
-LazyCallGraph::SCC::insertIncomingEdge(Node &CallerN, Node &CalleeN) {
+LazyCallGraph::SCC::insertIncomingEdge(Node &ParentN, Node &ChildN,
+ Edge::Kind EK) {
// First insert it into the caller.
- CallerN.insertEdgeInternal(CalleeN);
+ ParentN.insertEdgeInternal(ChildN, EK);
- assert(G->SCCMap.lookup(&CalleeN) == this && "Callee must be in this SCC.");
+ assert(G->SCCMap.lookup(&ChildN) == this && "Child must be in this SCC.");
- SCC &CallerC = *G->SCCMap.lookup(&CallerN);
- assert(&CallerC != this && "Caller must not be in this SCC.");
- assert(CallerC.isDescendantOf(*this) &&
- "Caller must be a descendant of the Callee.");
+ SCC &ParentC = *G->SCCMap.lookup(&ParentN);
+ assert(&ParentC != this && "Parent must not be in this SCC.");
+ assert(ParentC.isDescendantOf(*this) &&
+ "Parent must be a descendant of the Child.");
// The algorithm we use for merging SCCs based on the cycle introduced here
// is to walk the SCC inverted DAG formed by the parent SCC sets. The inverse
@@ -231,7 +247,7 @@ LazyCallGraph::SCC::insertIncomingEdge(Node &CallerN, Node &CalleeN) {
// participate in the merged connected component.
SmallPtrSet<SCC *, 8> ConnectedSCCs;
ConnectedSCCs.insert(this);
- ConnectedSCCs.insert(&CallerC);
+ ConnectedSCCs.insert(&ParentC);
// We build up a DFS stack of the parents chains.
SmallVector<std::pair<SCC *, SCC::parent_iterator>, 8> DFSSCCs;
@@ -298,8 +314,9 @@ LazyCallGraph::SCC::insertIncomingEdge(Node &CallerN, Node &CalleeN) {
C->ParentSCCs.clear();
for (Node *N : *C) {
- for (Node &ChildN : *N) {
- SCC &ChildC = *G->SCCMap.lookup(&ChildN);
+ for (Edge &E : *N) {
+ assert(E.getNode() && "Cannot have a null node within a visited SCC!");
+ SCC &ChildC = *G->SCCMap.lookup(E.getNode());
if (&ChildC != C)
ChildC.ParentSCCs.erase(C);
}
@@ -309,8 +326,9 @@ LazyCallGraph::SCC::insertIncomingEdge(Node &CallerN, Node &CalleeN) {
C->Nodes.clear();
}
for (auto I = Nodes.begin() + NewNodeBeginIdx, E = Nodes.end(); I != E; ++I)
- for (Node &ChildN : **I) {
- SCC &ChildC = *G->SCCMap.lookup(&ChildN);
+ for (Edge &E : **I) {
+ assert(E.getNode() && "Cannot have a null node within a visited SCC!");
+ SCC &ChildC = *G->SCCMap.lookup(E.getNode());
if (&ChildC != this)
ChildC.ParentSCCs.insert(this);
}
@@ -322,64 +340,65 @@ LazyCallGraph::SCC::insertIncomingEdge(Node &CallerN, Node &CalleeN) {
return SmallVector<SCC *, 1>(ConnectedSCCs.begin(), ConnectedSCCs.end());
}
-void LazyCallGraph::SCC::removeInterSCCEdge(Node &CallerN, Node &CalleeN) {
+void LazyCallGraph::SCC::removeInterSCCEdge(Node &ParentN, Node &ChildN) {
// First remove it from the node.
- CallerN.removeEdgeInternal(CalleeN.getFunction());
+ ParentN.removeEdgeInternal(ChildN.getFunction());
- assert(G->SCCMap.lookup(&CallerN) == this &&
+ assert(G->SCCMap.lookup(&ParentN) == this &&
"The caller must be a member of this SCC.");
- SCC &CalleeC = *G->SCCMap.lookup(&CalleeN);
- assert(&CalleeC != this &&
+ SCC &ChildC = *G->SCCMap.lookup(&ChildN);
+ assert(&ChildC != this &&
"This API only supports the rmoval of inter-SCC edges.");
assert(std::find(G->LeafSCCs.begin(), G->LeafSCCs.end(), this) ==
G->LeafSCCs.end() &&
"Cannot have a leaf SCC caller with a different SCC callee.");
- bool HasOtherCallToCalleeC = false;
- bool HasOtherCallOutsideSCC = false;
+ bool HasOtherEdgeToChildC = false;
+ bool HasOtherChildC = false;
for (Node *N : *this) {
- for (Node &OtherCalleeN : *N) {
- SCC &OtherCalleeC = *G->SCCMap.lookup(&OtherCalleeN);
- if (&OtherCalleeC == &CalleeC) {
- HasOtherCallToCalleeC = true;
+ for (Edge &E : *N) {
+ assert(E.getNode() && "Cannot have a missing node in a visited SCC!");
+ SCC &OtherChildC = *G->SCCMap.lookup(E.getNode());
+ if (&OtherChildC == &ChildC) {
+ HasOtherEdgeToChildC = true;
break;
}
- if (&OtherCalleeC != this)
- HasOtherCallOutsideSCC = true;
+ if (&OtherChildC != this)
+ HasOtherChildC = true;
}
- if (HasOtherCallToCalleeC)
+ if (HasOtherEdgeToChildC)
break;
}
// Because the SCCs form a DAG, deleting such an edge cannot change the set
// of SCCs in the graph. However, it may cut an edge of the SCC DAG, making
- // the caller no longer a parent of the callee. Walk the other call edges
- // in the caller to tell.
- if (!HasOtherCallToCalleeC) {
- bool Removed = CalleeC.ParentSCCs.erase(this);
+ // the parent SCC no longer connected to the child SCC. If so, we need to
+ // update the child SCC's map of its parents.
+ if (!HasOtherEdgeToChildC) {
+ bool Removed = ChildC.ParentSCCs.erase(this);
(void)Removed;
assert(Removed &&
- "Did not find the caller SCC in the callee SCC's parent list!");
+ "Did not find the parent SCC in the child SCC's parent list!");
// It may orphan an SCC if it is the last edge reaching it, but that does
// not violate any invariants of the graph.
- if (CalleeC.ParentSCCs.empty())
- DEBUG(dbgs() << "LCG: Update removing " << CallerN.getFunction().getName()
- << " -> " << CalleeN.getFunction().getName()
+ if (ChildC.ParentSCCs.empty())
+ DEBUG(dbgs() << "LCG: Update removing " << ParentN.getFunction().getName()
+ << " -> " << ChildN.getFunction().getName()
<< " edge orphaned the callee's SCC!\n");
}
- // It may make the Caller SCC a leaf SCC.
- if (!HasOtherCallOutsideSCC)
+ // It may make the Parent SCC a leaf SCC.
+ if (!HasOtherChildC)
G->LeafSCCs.push_back(this);
}
void LazyCallGraph::SCC::internalDFS(
- SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack,
+ SmallVectorImpl<std::pair<Node *, Node::edge_iterator>> &DFSStack,
SmallVectorImpl<Node *> &PendingSCCStack, Node *N,
SmallVectorImpl<SCC *> &ResultSCCs) {
- Node::iterator I = N->begin();
+ auto I = N->begin();
N->LowLink = N->DFSNumber = 1;
int NextDFSNumber = 2;
for (;;) {
@@ -387,9 +406,9 @@ void LazyCallGraph::SCC::internalDFS(
"before processing a node.");
// We simulate recursion by popping out of the nested loop and continuing.
- Node::iterator E = N->end();
+ auto E = N->end();
while (I != E) {
- Node &ChildN = *I;
+ Node &ChildN = I->getNode(*G);
if (SCC *ChildSCC = G->SCCMap.lookup(&ChildN)) {
// Check if we have reached a node in the new (known connected) set of
// this SCC. If so, the entire stack is necessarily in that set and we
@@ -455,15 +474,15 @@ void LazyCallGraph::SCC::internalDFS(
}
SmallVector<LazyCallGraph::SCC *, 1>
-LazyCallGraph::SCC::removeIntraSCCEdge(Node &CallerN, Node &CalleeN) {
+LazyCallGraph::SCC::removeIntraSCCEdge(Node &ParentN, Node &ChildN) {
// First remove it from the node.
- CallerN.removeEdgeInternal(CalleeN.getFunction());
+ ParentN.removeEdgeInternal(ChildN.getFunction());
// We return a list of the resulting *new* SCCs in postorder.
SmallVector<SCC *, 1> ResultSCCs;
// Direct recursion doesn't impact the SCC graph at all.
- if (&CallerN == &CalleeN)
+ if (&ParentN == &ChildN)
return ResultSCCs;
// The worklist is every node in the original SCC.
@@ -478,16 +497,16 @@ LazyCallGraph::SCC::removeIntraSCCEdge(Node &CallerN, Node &CalleeN) {
assert(Worklist.size() > 1 && "We have to have at least two nodes to have an "
"edge between them that is within the SCC.");
- // The callee can already reach every node in this SCC (by definition). It is
+ // The child can already reach every node in this SCC (by definition). It is
// the only node we know will stay inside this SCC. Everything which
- // transitively reaches Callee will also remain in the SCC. To model this we
+ // transitively reaches Child will also remain in the SCC. To model this we
// incrementally add any chain of nodes which reaches something in the new
// node set to the new node set. This short circuits one side of the Tarjan's
// walk.
- insert(CalleeN);
+ insert(ChildN);
// We're going to do a full mini-Tarjan's walk using a local stack here.
- SmallVector<std::pair<Node *, Node::iterator>, 4> DFSStack;
+ SmallVector<std::pair<Node *, Node::edge_iterator>, 4> DFSStack;
SmallVector<Node *, 4> PendingSCCStack;
do {
Node *N = Worklist.pop_back_val();
@@ -501,8 +520,9 @@ LazyCallGraph::SCC::removeIntraSCCEdge(Node &CallerN, Node &CalleeN) {
// Now we need to reconnect the current SCC to the graph.
bool IsLeafSCC = true;
for (Node *N : Nodes) {
- for (Node &ChildN : *N) {
- SCC &ChildSCC = *G->SCCMap.lookup(&ChildN);
+ for (Edge &E : *N) {
+ assert(E.getNode() && "Cannot have a missing node in a visited SCC!");
+ SCC &ChildSCC = *G->SCCMap.lookup(E.getNode());
if (&ChildSCC == this)
continue;
ChildSCC.ParentSCCs.insert(this);
@@ -528,18 +548,18 @@ LazyCallGraph::SCC::removeIntraSCCEdge(Node &CallerN, Node &CalleeN) {
return ResultSCCs;
}
-void LazyCallGraph::insertEdge(Node &CallerN, Function &Callee) {
+void LazyCallGraph::insertEdge(Node &ParentN, Function &Child, Edge::Kind EK) {
assert(SCCMap.empty() && DFSStack.empty() &&
"This method cannot be called after SCCs have been formed!");
- return CallerN.insertEdgeInternal(Callee);
+ return ParentN.insertEdgeInternal(Child, EK);
}
-void LazyCallGraph::removeEdge(Node &CallerN, Function &Callee) {
+void LazyCallGraph::removeEdge(Node &ParentN, Function &Child) {
assert(SCCMap.empty() && DFSStack.empty() &&
"This method cannot be called after SCCs have been formed!");
- return CallerN.removeEdgeInternal(Callee);
+ return ParentN.removeEdgeInternal(Child);
}
LazyCallGraph::Node &LazyCallGraph::insertInto(Function &F, Node *&MappedN) {
@@ -550,17 +570,16 @@ void LazyCallGraph::updateGraphPtrs() {
// Process all nodes updating the graph pointers.
{
SmallVector<Node *, 16> Worklist;
- for (auto &Entry : EntryNodes)
- if (Node *EntryN = Entry.dyn_cast<Node *>())
+ for (Edge &E : EntryEdges)
+ if (Node *EntryN = E.getNode())
Worklist.push_back(EntryN);
while (!Worklist.empty()) {
Node *N = Worklist.pop_back_val();
N->G = this;
- for (auto &Callee : N->Callees)
- if (!Callee.isNull())
- if (Node *CalleeN = Callee.dyn_cast<Node *>())
- Worklist.push_back(CalleeN);
+ for (Edge &E : N->Edges)
+ if (Node *ChildN = E.getNode())
+ Worklist.push_back(ChildN);
}
}
@@ -596,8 +615,9 @@ LazyCallGraph::SCC *LazyCallGraph::formSCC(Node *RootN,
// its children.
bool IsLeafSCC = true;
for (Node *SCCN : NewSCC->Nodes)
- for (Node &SCCChildN : *SCCN) {
- SCC &ChildSCC = *SCCMap.lookup(&SCCChildN);
+ for (Edge &E : *SCCN) {
+ assert(E.getNode() && "Cannot have a missing node in a visited SCC!");
+ SCC &ChildSCC = *SCCMap.lookup(E.getNode());
if (&ChildSCC == NewSCC)
continue;
ChildSCC.ParentSCCs.insert(NewSCC);
@@ -613,7 +633,7 @@ LazyCallGraph::SCC *LazyCallGraph::formSCC(Node *RootN,
LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
Node *N;
- Node::iterator I;
+ Node::edge_iterator I;
if (!DFSStack.empty()) {
N = DFSStack.back().first;
I = DFSStack.back().second;
@@ -635,9 +655,9 @@ LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
assert(N->DFSNumber != 0 && "We should always assign a DFS number "
"before placing a node onto the stack.");
- Node::iterator E = N->end();
+ auto E = N->end();
while (I != E) {
- Node &ChildN = *I;
+ Node &ChildN = I->getNode(*this);
if (ChildN.DFSNumber == 0) {
// Mark that we should start at this child when next this node is the
// top of the stack. We don't start at the next child to ensure this
@@ -686,14 +706,19 @@ LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
static void printNodes(raw_ostream &OS, LazyCallGraph::Node &N,
SmallPtrSetImpl<LazyCallGraph::Node *> &Printed) {
+ LazyCallGraph &G = N.getGraph();
+
// Recurse depth first through the nodes.
- for (LazyCallGraph::Node &ChildN : N)
+ for (LazyCallGraph::Edge &E : N) {
+ LazyCallGraph::Node &ChildN = E.getNode(G);
if (Printed.insert(&ChildN).second)
printNodes(OS, ChildN, Printed);
+ }
- OS << " Call edges in function: " << N.getFunction().getName() << "\n";
- for (LazyCallGraph::iterator I = N.begin(), E = N.end(); I != E; ++I)
- OS << " -> " << I->getFunction().getName() << "\n";
+ OS << " Edges in function: " << N.getFunction().getName() << "\n";
+ for (const LazyCallGraph::Edge &E : N)
+ OS << " " << (E.isCall() ? "call" : "ref ") << " -> "
+ << E.getFunction().getName() << "\n";
OS << "\n";
}
@@ -716,9 +741,11 @@ PreservedAnalyses LazyCallGraphPrinterPass::run(Module &M,
<< "\n\n";
SmallPtrSet<LazyCallGraph::Node *, 16> Printed;
- for (LazyCallGraph::Node &N : G)
+ for (LazyCallGraph::Edge &E : G) {
+ LazyCallGraph::Node &N = E.getNode(G);
if (Printed.insert(&N).second)
printNodes(OS, N, Printed);
+ }
for (LazyCallGraph::SCC &SCC : G.postorder_sccs())
printSCC(OS, SCC);
OpenPOWER on IntegriCloud