forked from OSchip/llvm-project
Re-land "Add LazyCallGraph API to add function to RefSCC"
This re-commits https://reviews.llvm.org/D70927, which I reverted in https://reviews.llvm.org/rG28213680b2a7d1fdeea16aa3f3a368879472c72a due to a buildbot error: http://lab.llvm.org:8011/builders/clang-cmake-x86_64-avx2-linux/builds/13251 I no longer include a test case that appears to crash when built with the buildbot's compiler, GCC 5.4.0.
This commit is contained in:
parent
612c4bf09e
commit
0deef2e164
|
@ -1061,6 +1061,10 @@ public:
|
||||||
/// Introduce a node for the function \p NewF in the SCC \p C.
|
/// Introduce a node for the function \p NewF in the SCC \p C.
|
||||||
void addNewFunctionIntoSCC(Function &NewF, SCC &C);
|
void addNewFunctionIntoSCC(Function &NewF, SCC &C);
|
||||||
|
|
||||||
|
/// Introduce a node for the function \p NewF, as a single node in a
|
||||||
|
/// new SCC, in the RefSCC \p RC.
|
||||||
|
void addNewFunctionIntoRefSCC(Function &NewF, RefSCC &RC);
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
///@{
|
///@{
|
||||||
|
@ -1167,6 +1171,13 @@ private:
|
||||||
/// Helper to update pointers back to the graph object during moves.
|
/// Helper to update pointers back to the graph object during moves.
|
||||||
void updateGraphPtrs();
|
void updateGraphPtrs();
|
||||||
|
|
||||||
|
/// Helper to insert a new function, add it to the NodeMap, and populate its
|
||||||
|
/// node.
|
||||||
|
Node &createNode(Function &F);
|
||||||
|
|
||||||
|
/// Helper to add the given Node \p N to the SCCMap, mapped to the SCC \p C.
|
||||||
|
void addNodeToSCC(SCC &C, Node &N);
|
||||||
|
|
||||||
/// Allocates an SCC and constructs it using the graph allocator.
|
/// Allocates an SCC and constructs it using the graph allocator.
|
||||||
///
|
///
|
||||||
/// The arguments are forwarded to the constructor.
|
/// The arguments are forwarded to the constructor.
|
||||||
|
|
|
@ -1567,12 +1567,17 @@ void LazyCallGraph::removeDeadFunction(Function &F) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LazyCallGraph::addNewFunctionIntoSCC(Function &NewF, SCC &C) {
|
void LazyCallGraph::addNewFunctionIntoSCC(Function &NewF, SCC &C) {
|
||||||
Node &CGNode = get(NewF);
|
addNodeToSCC(C, createNode(NewF));
|
||||||
CGNode.DFSNumber = CGNode.LowLink = -1;
|
}
|
||||||
CGNode.populate();
|
|
||||||
C.Nodes.push_back(&CGNode);
|
void LazyCallGraph::addNewFunctionIntoRefSCC(Function &NewF, RefSCC &RC) {
|
||||||
SCCMap[&CGNode] = &C;
|
Node &N = createNode(NewF);
|
||||||
NodeMap[&NewF] = &CGNode;
|
|
||||||
|
auto *C = createSCC(RC, SmallVector<Node *, 1>());
|
||||||
|
addNodeToSCC(*C, N);
|
||||||
|
|
||||||
|
RC.SCCIndices[C] = RC.SCCIndices.size();
|
||||||
|
RC.SCCs.push_back(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyCallGraph::Node &LazyCallGraph::insertInto(Function &F, Node *&MappedN) {
|
LazyCallGraph::Node &LazyCallGraph::insertInto(Function &F, Node *&MappedN) {
|
||||||
|
@ -1589,6 +1594,21 @@ void LazyCallGraph::updateGraphPtrs() {
|
||||||
RC->G = this;
|
RC->G = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyCallGraph::Node &LazyCallGraph::createNode(Function &F) {
|
||||||
|
assert(!lookup(F) && "node already exists");
|
||||||
|
|
||||||
|
Node &N = get(F);
|
||||||
|
NodeMap[&F] = &N;
|
||||||
|
N.DFSNumber = N.LowLink = -1;
|
||||||
|
N.populate();
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyCallGraph::addNodeToSCC(LazyCallGraph::SCC &C, Node &N) {
|
||||||
|
C.Nodes.push_back(&N);
|
||||||
|
SCCMap[&N] = &C;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename RootsT, typename GetBeginT, typename GetEndT,
|
template <typename RootsT, typename GetBeginT, typename GetEndT,
|
||||||
typename GetNodeT, typename FormSCCCallbackT>
|
typename GetNodeT, typename FormSCCCallbackT>
|
||||||
void LazyCallGraph::buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
|
void LazyCallGraph::buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
|
||||||
|
|
|
@ -2210,4 +2210,46 @@ TEST(LazyCallGraphTest, RemoveFunctionWithSpurriousRef) {
|
||||||
EXPECT_EQ(&RC2, &*I++);
|
EXPECT_EQ(&RC2, &*I++);
|
||||||
EXPECT_EQ(CG.postorder_ref_scc_end(), I);
|
EXPECT_EQ(CG.postorder_ref_scc_end(), I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(LazyCallGraphTest, AddNewFunctionIntoRefSCC) {
|
||||||
|
LLVMContext Context;
|
||||||
|
// Build and populate a graph composed of a single, self-referential node.
|
||||||
|
std::unique_ptr<Module> M = parseAssembly(Context, "define void @f() {\n"
|
||||||
|
"entry:\n"
|
||||||
|
" call void @f()\n"
|
||||||
|
" ret void\n"
|
||||||
|
"}\n");
|
||||||
|
LazyCallGraph CG = buildCG(*M);
|
||||||
|
CG.buildRefSCCs();
|
||||||
|
|
||||||
|
// At this point 'f' is in the call graph.
|
||||||
|
auto &F = lookupFunction(*M, "f");
|
||||||
|
LazyCallGraph::Node *FN = CG.lookup(F);
|
||||||
|
EXPECT_NE(FN, nullptr);
|
||||||
|
|
||||||
|
// And it has an SCC, of course.
|
||||||
|
auto *FSCC = CG.lookupSCC(*FN);
|
||||||
|
EXPECT_NE(FSCC, nullptr);
|
||||||
|
|
||||||
|
// Now, create a new function 'g'.
|
||||||
|
auto *G = Function::Create(F.getFunctionType(), F.getLinkage(),
|
||||||
|
F.getAddressSpace(), "g", F.getParent());
|
||||||
|
BasicBlock::Create(F.getParent()->getContext(), "entry", G);
|
||||||
|
|
||||||
|
// Instruct the LazyCallGraph to create a new node for 'g', within the same
|
||||||
|
// RefSCC as 'f', but in a separate SCC.
|
||||||
|
CG.addNewFunctionIntoRefSCC(*G, FSCC->getOuterRefSCC());
|
||||||
|
|
||||||
|
// 'g' should now be in the call graph.
|
||||||
|
LazyCallGraph::Node *GN = CG.lookup(*G);
|
||||||
|
EXPECT_NE(GN, nullptr);
|
||||||
|
// 'g' should have an SCC, composed of the singular node 'g'.
|
||||||
|
// ('f' should not be included in the 'g' SCC.)
|
||||||
|
LazyCallGraph::SCC *GSCC = CG.lookupSCC(*GN);
|
||||||
|
EXPECT_NE(GSCC, nullptr);
|
||||||
|
EXPECT_EQ(GSCC->size(), 1);
|
||||||
|
EXPECT_NE(GSCC, FSCC);
|
||||||
|
// 'g' and 'f' should be part of the same RefSCC.
|
||||||
|
EXPECT_EQ(&GSCC->getOuterRefSCC(), &FSCC->getOuterRefSCC());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue