[LCG] Hoist the logic for forming a new SCC from the top of the DFSStack
into a helper function. I plan to re-use it for doing incremental DFS-based updates to the SCCs when we mutate the call graph. llvm-svn: 206948
This commit is contained in:
parent
cd8c610cb0
commit
3f9869a8e2
|
@ -364,6 +364,11 @@ private:
|
||||||
/// \brief Helper to update pointers back to the graph object during moves.
|
/// \brief Helper to update pointers back to the graph object during moves.
|
||||||
void updateGraphPtrs();
|
void updateGraphPtrs();
|
||||||
|
|
||||||
|
/// \brief Helper to form a new SCC out of the top of a DFSStack-like
|
||||||
|
/// structure.
|
||||||
|
SCC *formSCCFromDFSStack(
|
||||||
|
SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack);
|
||||||
|
|
||||||
/// \brief Retrieve the next node in the post-order SCC walk of the call graph.
|
/// \brief Retrieve the next node in the post-order SCC walk of the call graph.
|
||||||
SCC *getNextSCCInPostOrder();
|
SCC *getNextSCCInPostOrder();
|
||||||
};
|
};
|
||||||
|
|
|
@ -151,6 +151,51 @@ void LazyCallGraph::updateGraphPtrs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyCallGraph::SCC *LazyCallGraph::formSCCFromDFSStack(
|
||||||
|
SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack) {
|
||||||
|
// The tail of the stack is the new SCC. Allocate the SCC and pop the stack
|
||||||
|
// into it.
|
||||||
|
SCC *NewSCC = new (SCCBPA.Allocate()) SCC();
|
||||||
|
|
||||||
|
// Because we don't follow the strict Tarjan recursive formulation, walk
|
||||||
|
// from the top of the stack down, propagating the lowest link and stopping
|
||||||
|
// when the DFS number is the lowest link.
|
||||||
|
int LowestLink = DFSStack.back().first->LowLink;
|
||||||
|
do {
|
||||||
|
Node *SCCN = DFSStack.pop_back_val().first;
|
||||||
|
SCCMap[&SCCN->getFunction()] = NewSCC;
|
||||||
|
NewSCC->Nodes.push_back(SCCN);
|
||||||
|
LowestLink = std::min(LowestLink, SCCN->LowLink);
|
||||||
|
bool Inserted =
|
||||||
|
NewSCC->NodeSet.insert(&SCCN->getFunction());
|
||||||
|
(void)Inserted;
|
||||||
|
assert(Inserted && "Cannot have duplicates in the DFSStack!");
|
||||||
|
} while (!DFSStack.empty() && LowestLink <= DFSStack.back().first->DFSNumber);
|
||||||
|
assert(LowestLink == NewSCC->Nodes.back()->DFSNumber &&
|
||||||
|
"Cannot stop with a DFS number greater than the lowest link!");
|
||||||
|
|
||||||
|
// A final pass over all edges in the SCC (this remains linear as we only
|
||||||
|
// do this once when we build the SCC) to connect it to the parent sets of
|
||||||
|
// its children.
|
||||||
|
bool IsLeafSCC = true;
|
||||||
|
for (Node *SCCN : NewSCC->Nodes)
|
||||||
|
for (Node *SCCChildN : *SCCN) {
|
||||||
|
if (NewSCC->NodeSet.count(&SCCChildN->getFunction()))
|
||||||
|
continue;
|
||||||
|
SCC *ChildSCC = SCCMap.lookup(&SCCChildN->getFunction());
|
||||||
|
assert(ChildSCC &&
|
||||||
|
"Must have all child SCCs processed when building a new SCC!");
|
||||||
|
ChildSCC->ParentSCCs.insert(NewSCC);
|
||||||
|
IsLeafSCC = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the SCCs where we fine no child SCCs, add them to the leaf list.
|
||||||
|
if (IsLeafSCC)
|
||||||
|
LeafSCCs.push_back(NewSCC);
|
||||||
|
|
||||||
|
return NewSCC;
|
||||||
|
}
|
||||||
|
|
||||||
LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
|
LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
|
||||||
// When the stack is empty, there are no more SCCs to walk in this graph.
|
// When the stack is empty, there are no more SCCs to walk in this graph.
|
||||||
if (DFSStack.empty()) {
|
if (DFSStack.empty()) {
|
||||||
|
@ -190,47 +235,8 @@ LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
|
||||||
N->LowLink = ChildN->LowLink;
|
N->LowLink = ChildN->LowLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tail of the stack is the new SCC. Allocate the SCC and pop the stack
|
// Form the new SCC out of the top of the DFS stack.
|
||||||
// into it.
|
return formSCCFromDFSStack(DFSStack);
|
||||||
SCC *NewSCC = new (SCCBPA.Allocate()) SCC();
|
|
||||||
|
|
||||||
// Because we don't follow the strict Tarjan recursive formulation, walk
|
|
||||||
// from the top of the stack down, propagating the lowest link and stopping
|
|
||||||
// when the DFS number is the lowest link.
|
|
||||||
int LowestLink = N->LowLink;
|
|
||||||
do {
|
|
||||||
Node *SCCN = DFSStack.pop_back_val().first;
|
|
||||||
SCCMap.insert(std::make_pair(&SCCN->getFunction(), NewSCC));
|
|
||||||
NewSCC->Nodes.push_back(SCCN);
|
|
||||||
LowestLink = std::min(LowestLink, SCCN->LowLink);
|
|
||||||
bool Inserted =
|
|
||||||
NewSCC->NodeSet.insert(&SCCN->getFunction());
|
|
||||||
(void)Inserted;
|
|
||||||
assert(Inserted && "Cannot have duplicates in the DFSStack!");
|
|
||||||
} while (!DFSStack.empty() && LowestLink <= DFSStack.back().first->DFSNumber);
|
|
||||||
assert(LowestLink == NewSCC->Nodes.back()->DFSNumber &&
|
|
||||||
"Cannot stop with a DFS number greater than the lowest link!");
|
|
||||||
|
|
||||||
// A final pass over all edges in the SCC (this remains linear as we only
|
|
||||||
// do this once when we build the SCC) to connect it to the parent sets of
|
|
||||||
// its children.
|
|
||||||
bool IsLeafSCC = true;
|
|
||||||
for (Node *SCCN : NewSCC->Nodes)
|
|
||||||
for (Node *SCCChildN : *SCCN) {
|
|
||||||
if (NewSCC->NodeSet.count(&SCCChildN->getFunction()))
|
|
||||||
continue;
|
|
||||||
SCC *ChildSCC = SCCMap.lookup(&SCCChildN->getFunction());
|
|
||||||
assert(ChildSCC &&
|
|
||||||
"Must have all child SCCs processed when building a new SCC!");
|
|
||||||
ChildSCC->ParentSCCs.insert(NewSCC);
|
|
||||||
IsLeafSCC = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the SCCs where we fine no child SCCs, add them to the leaf list.
|
|
||||||
if (IsLeafSCC)
|
|
||||||
LeafSCCs.push_back(NewSCC);
|
|
||||||
|
|
||||||
return NewSCC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char LazyCallGraphAnalysis::PassID;
|
char LazyCallGraphAnalysis::PassID;
|
||||||
|
|
Loading…
Reference in New Issue