[PATCH] D72226: Short-circuit SCC update for self-referential edge
Brian Gesiak via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 5 05:34:21 PST 2020
modocache created this revision.
modocache added reviewers: jdoerfert, chandlerc, wenlei.
Herald added subscribers: hiraditya, mehdi_amini.
Herald added a project: LLVM.
Depends on https://reviews.llvm.org/D70927.
When switching a call egde to a ref edge within the same SCC, special
care is taken to update the SCC in case the strongly-connected cycle is
broken. However, for self referential edges, it is not possible for the
switch from call edge to ref edge to break a cycle -- all nodes form a
strongly-connected cycle with themselves, regardless of any
self-referential call or ref edges.
Adding short-circuiting behavior prevents unnecessary DFS in some cases.
In other cases, such as when using the CallGraphUpdater, the
short-circuit prevents an assertion within 'incorporateNewSCCRange' from
firing. In that case, the DFS update over the nodes in the graph
erroneously create new SCCs.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D72226
Files:
llvm/lib/Analysis/LazyCallGraph.cpp
llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
Index: llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
===================================================================
--- llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
+++ llvm/unittests/Analysis/CGSCCPassManagerTest.cpp
@@ -1560,5 +1560,55 @@
MPM.run(*M, MAM);
}
+TEST_F(CGSCCPassManagerTest, TestDemotionOfSelfReferentialCallEdge) {
+ std::unique_ptr<Module> M = parseIR("define void @f() {\n"
+ "entry:\n"
+ " call void @f()\n"
+ " ret void\n"
+ "}\n");
+
+ CGSCCPassManager CGPM(/*DebugLogging*/ true);
+ CGPM.addPass(LambdaSCCPassNoPreserve(
+ [&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
+ CGSCCUpdateResult &UR) {
+ CallGraphUpdater CGUpdater(CG, AM, UR);
+ for (auto &N : C) {
+ auto &F = N.getFunction();
+ if (F.getName() != "f")
+ continue;
+ auto *Call = dyn_cast<CallInst>(F.begin()->begin());
+ if (!Call || Call->getCalledFunction()->getName() != "f")
+ continue;
+
+ // "Demote" the 'f -> f' call egde to a ref edge.
+ // 1. Erase the call edge from 'f' to 'f'.
+ Call->eraseFromParent();
+ // 2. Insert a ref edge from 'f' to 'f'.
+ (void)CastInst::CreatePointerCast(&F,
+ Type::getInt8PtrTy(F.getContext()),
+ "f.ref", &*F.begin()->begin());
+
+ // Create a new function 'g' and use the CallGraphUpdater to insert
+ // a node for 'g' into the call graph. This also connects creates a
+ // ref edge 'f -> g'.
+ auto *G =
+ llvm::Function::Create(F.getFunctionType(), F.getLinkage(),
+ F.getAddressSpace(), "g", F.getParent());
+ llvm::BasicBlock::Create(F.getParent()->getContext(), "entry", G);
+ CGUpdater.registerOutlinedFunction(*G, &C);
+
+ ASSERT_NO_FATAL_FAILURE(
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR))
+ << "Updating the call graph with a demoted, self-referential "
+ "call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
+ "caused a fatal failure";
+ }
+ }));
+
+ ModulePassManager MPM(/*DebugLogging*/ true);
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
+ MPM.run(*M, MAM);
+}
+
#endif
} // namespace
Index: llvm/lib/Analysis/LazyCallGraph.cpp
===================================================================
--- llvm/lib/Analysis/LazyCallGraph.cpp
+++ llvm/lib/Analysis/LazyCallGraph.cpp
@@ -721,8 +721,14 @@
// Set the edge kind.
SourceN->setEdgeKind(TargetN, Edge::Ref);
- // Otherwise we are removing a call edge from a single SCC. This may break
- // the cycle. In order to compute the new set of SCCs, we need to do a small
+ // Otherwise, we are removing a call edge from a single SCC. This may break
+ // the cycle. However, one trivial case remains that we check for now: a
+ // node is always strongly connected to itself, so demoting an edge from a
+ // node to itself cannot break a cycle, and does not introduce any new SCCs.
+ if (&SourceN == &TargetN)
+ return range(iterator(), iterator());
+
+ // In order to compute the new set of SCCs, we need to do a small
// DFS over the nodes within the SCC to form any sub-cycles that remain as
// distinct SCCs and compute a postorder over the resulting SCCs.
//
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72226.236238.patch
Type: text/x-patch
Size: 3637 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200105/9185a1e3/attachment.bin>
More information about the llvm-commits
mailing list