findCallees(Worklist, Visited, Callees, CalleeIndexMap);
}
+void LazyCallGraph::Node::insertEdgeInternal(Function &Callee) {
+ if (Node *N = G->lookup(Callee))
+ return insertEdgeInternal(*N);
+
+ CalleeIndexMap.insert(std::make_pair(&Callee, Callees.size()));
+ Callees.push_back(&Callee);
+}
+
+void LazyCallGraph::Node::insertEdgeInternal(Node &CalleeN) {
+ CalleeIndexMap.insert(std::make_pair(&CalleeN.getFunction(), Callees.size()));
+ Callees.push_back(&CalleeN);
+}
+
void LazyCallGraph::Node::removeEdgeInternal(Function &Callee) {
auto IndexMapI = CalleeIndexMap.find(&Callee);
assert(IndexMapI != CalleeIndexMap.end() &&
"Callee not in the callee set for this caller?");
- Callees.erase(Callees.begin() + IndexMapI->second);
+ Callees[IndexMapI->second] = nullptr;
CalleeIndexMap.erase(IndexMapI);
}
"entry set.\n");
findCallees(Worklist, Visited, EntryNodes, EntryIndexMap);
- for (auto &Entry : EntryNodes)
+ 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());
+ }
}
LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)
G->SCCMap[&N] = this;
}
+void LazyCallGraph::SCC::insertIntraSCCEdge(Node &CallerN, Node &CalleeN) {
+ // First insert it into the caller.
+ CallerN.insertEdgeInternal(CalleeN);
+
+ assert(G->SCCMap.lookup(&CallerN) == this && "Caller must be in this SCC.");
+ assert(G->SCCMap.lookup(&CalleeN) == this && "Callee must be in this SCC.");
+
+ // Nothing changes about this SCC or any other.
+}
+
void LazyCallGraph::SCC::removeInterSCCEdge(Node &CallerN, Node &CalleeN) {
// First remove it from the node.
CallerN.removeEdgeInternal(CalleeN.getFunction());
// First remove it from the node.
CallerN.removeEdgeInternal(CalleeN.getFunction());
- // We return a list of the resulting SCCs, where 'this' is always the first
- // element.
+ // We return a list of the resulting *new* SCCs in postorder.
SmallVector<SCC *, 1> ResultSCCs;
- ResultSCCs.push_back(this);
// Direct recursion doesn't impact the SCC graph at all.
if (&CallerN == &CalleeN)
}
}
#ifndef NDEBUG
- if (ResultSCCs.size() > 1)
+ if (!ResultSCCs.empty())
assert(!IsLeafSCC && "This SCC cannot be a leaf as we have split out new "
"SCCs by removing this edge.");
if (!std::any_of(G->LeafSCCs.begin(), G->LeafSCCs.end(),
#endif
// If this SCC stopped being a leaf through this edge removal, remove it from
// the leaf SCC list.
- if (!IsLeafSCC && ResultSCCs.size() > 1)
+ if (!IsLeafSCC && !ResultSCCs.empty())
G->LeafSCCs.erase(std::remove(G->LeafSCCs.begin(), G->LeafSCCs.end(), this),
G->LeafSCCs.end());
return ResultSCCs;
}
+void LazyCallGraph::insertEdge(Node &CallerN, Function &Callee) {
+ assert(SCCMap.empty() && DFSStack.empty() &&
+ "This method cannot be called after SCCs have been formed!");
+
+ return CallerN.insertEdgeInternal(Callee);
+}
+
void LazyCallGraph::removeEdge(Node &CallerN, Function &Callee) {
assert(SCCMap.empty() && DFSStack.empty() &&
"This method cannot be called after SCCs have been formed!");
Node *N = Worklist.pop_back_val();
N->G = this;
for (auto &Callee : N->Callees)
- if (Node *CalleeN = Callee.dyn_cast<Node *>())
- Worklist.push_back(CalleeN);
+ if (!Callee.isNull())
+ if (Node *CalleeN = Callee.dyn_cast<Node *>())
+ Worklist.push_back(CalleeN);
}
}