[llvm] c662103 - [Coroutines][LazyCallGraph] addSplitRefRecursiveFunctions allows spurious ref edges between new functions. (#116285)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 14 13:55:09 PST 2025
Author: Tyler Nowicki
Date: 2025-02-14T16:55:06-05:00
New Revision: c662103c6ead3bbfad9bc24d7770552163dbb92b
URL: https://github.com/llvm/llvm-project/commit/c662103c6ead3bbfad9bc24d7770552163dbb92b
DIFF: https://github.com/llvm/llvm-project/commit/c662103c6ead3bbfad9bc24d7770552163dbb92b.diff
LOG: [Coroutines][LazyCallGraph] addSplitRefRecursiveFunctions allows spurious ref edges between new functions. (#116285)
The addSplitRefRecursiveFunctions LazyCallGraph helper should not
require a reference between every new function. Spurious ref edges
between the new functions are allowed and the new function are
considered to be a RefSCC. This change clarifies that this is the case
in the method's description and its DEBUG mode verifier.
Added:
Modified:
llvm/include/llvm/Analysis/LazyCallGraph.h
llvm/lib/Analysis/LazyCallGraph.cpp
llvm/unittests/Analysis/LazyCallGraphTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/LazyCallGraph.h b/llvm/include/llvm/Analysis/LazyCallGraph.h
index 289e9c3990bcc..a69ed91b0465e 100644
--- a/llvm/include/llvm/Analysis/LazyCallGraph.h
+++ b/llvm/include/llvm/Analysis/LazyCallGraph.h
@@ -1082,11 +1082,16 @@ class LazyCallGraph {
/// Add new ref-recursive functions split/outlined from an existing function.
///
/// The new functions may only reference other functions that the original
- /// function did. The new functions may reference (not call) the original
- /// function.
+ /// function did. The new functions may reference the original function. New
+ /// functions must not call other new functions or the original function.
///
- /// The original function must reference (not call) all new functions.
- /// All new functions must reference (not call) each other.
+ /// Marks the original function as referencing all new functions.
+ ///
+ /// It is not necessary for each new function to reference all other new
+ /// functions. Spurious/missing ref edges are allowed. The new functions
+ /// are considered to be a RefSCC. If any new function references the
+ /// original function they are all considered to be part of the original
+ /// function's RefSCC.
void addSplitRefRecursiveFunctions(Function &OriginalFunction,
ArrayRef<Function *> NewFunctions);
diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp
index 5aa36bfc36d46..eb91b7673afee 100644
--- a/llvm/lib/Analysis/LazyCallGraph.cpp
+++ b/llvm/lib/Analysis/LazyCallGraph.cpp
@@ -1720,6 +1720,7 @@ void LazyCallGraph::addSplitRefRecursiveFunctions(
for (Function *NewFunction : NewFunctions) {
Node &NewN = initNode(*NewFunction);
+ // Make the original function reference each new function
OriginalN->insertEdgeInternal(NewN, Edge::Kind::Ref);
// Check if there is any edge from any new function back to any function in
@@ -1775,8 +1776,9 @@ void LazyCallGraph::addSplitRefRecursiveFunctions(
if (F1 == F2)
continue;
Node &N2 = get(*F2);
- assert(!N1->lookup(N2)->isCall() &&
- "Edges between new functions must be ref edges");
+ assert(!N1->lookup(N2) ||
+ (!N1->lookup(N2)->isCall() &&
+ "Edges between new functions must be ref edges"));
}
}
#endif
diff --git a/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/llvm/unittests/Analysis/LazyCallGraphTest.cpp
index 6ca233a50f31f..311c5d470f2cc 100644
--- a/llvm/unittests/Analysis/LazyCallGraphTest.cpp
+++ b/llvm/unittests/Analysis/LazyCallGraphTest.cpp
@@ -3027,4 +3027,58 @@ TEST(LazyCallGraphTest, AddSplitFunctions5) {
EXPECT_EQ(RC, CG.lookupRefSCC(F2N));
EXPECT_EQ(CG.postorder_ref_scc_end(), I);
}
+
+TEST(LazyCallGraphTest, AddSplitFunctions6) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M = parseAssembly(Context, "define void @f() {\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG = buildCG(*M);
+
+ Function &F = lookupFunction(*M, "f");
+ LazyCallGraph::Node &FN = CG.get(F);
+
+ // Force the graph to be fully expanded.
+ CG.buildRefSCCs();
+ auto I = CG.postorder_ref_scc_begin();
+ LazyCallGraph::RefSCC *ORC = &*I++;
+ EXPECT_EQ(CG.postorder_ref_scc_end(), I);
+
+ auto *G1 = Function::Create(F.getFunctionType(), F.getLinkage(),
+ F.getAddressSpace(), "g1", F.getParent());
+ auto *G2 = Function::Create(F.getFunctionType(), F.getLinkage(),
+ F.getAddressSpace(), "g2", F.getParent());
+ BasicBlock *G1BB = BasicBlock::Create(Context, "", G1);
+ BasicBlock *G2BB = BasicBlock::Create(Context, "", G2);
+ // Create g1 -ref-> g2 and g2 has no references.
+ (void)CastInst::CreatePointerCast(G2, PointerType::getUnqual(Context), "",
+ G1BB);
+ (void)ReturnInst::Create(Context, G1BB);
+ (void)ReturnInst::Create(Context, G2BB);
+
+ // Create f -ref-> g1 and f -ref-> g2.
+ (void)CastInst::CreatePointerCast(G1, PointerType::getUnqual(Context), "",
+ F.getEntryBlock().begin());
+ (void)CastInst::CreatePointerCast(G2, PointerType::getUnqual(Context), "",
+ F.getEntryBlock().begin());
+
+ EXPECT_FALSE(verifyModule(*M, &errs()));
+
+ CG.addSplitRefRecursiveFunctions(F, SmallVector<Function *, 1>({G1, G2}));
+
+ LazyCallGraph::Node *G1N = CG.lookup(*G1);
+ EXPECT_TRUE(G1N);
+ LazyCallGraph::Node *G2N = CG.lookup(*G2);
+ EXPECT_TRUE(G2N);
+
+ I = CG.postorder_ref_scc_begin();
+ LazyCallGraph::RefSCC *RC1 = &*I++;
+ EXPECT_EQ(2, RC1->size());
+ EXPECT_EQ(RC1, CG.lookupRefSCC(*G1N));
+ EXPECT_EQ(RC1, CG.lookupRefSCC(*G2N));
+ LazyCallGraph::RefSCC *RC2 = &*I++;
+ EXPECT_EQ(RC2, ORC);
+ EXPECT_EQ(RC2, CG.lookupRefSCC(FN));
+ EXPECT_EQ(CG.postorder_ref_scc_end(), I);
+}
}
More information about the llvm-commits
mailing list