Skip to content

Commit 8d800e6

Browse files
authored
[CGSCC] Remove CGSCCUpdateResult::InvalidatedRefSCCs (llvm#98213)
The RefSCC that a function marked dead is in may still contain valid SCCs that we want to visit. We rely on InvalidatedSCCs to skip SCCs containing dead functions. The addition of RefSCCs in CallGraphUpdater to InvalidatedRefSCCs was causing asserts as reported in llvm#94815. Fix some more CallGraphUpdater function deletion methods as well.
1 parent 953c669 commit 8d800e6

File tree

4 files changed

+58
-25
lines changed

4 files changed

+58
-25
lines changed

llvm/include/llvm/Analysis/CGSCCPassManager.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,6 @@ struct CGSCCUpdateResult {
245245
/// in reverse post-order.
246246
SmallPriorityWorklist<LazyCallGraph::SCC *, 1> &CWorklist;
247247

248-
/// The set of invalidated RefSCCs which should be skipped if they are found
249-
/// in \c RCWorklist.
250-
///
251-
/// This is used to quickly prune out RefSCCs when they get deleted and
252-
/// happen to already be on the worklist. We use this primarily to avoid
253-
/// scanning the list and removing entries from it.
254-
SmallPtrSetImpl<LazyCallGraph::RefSCC *> &InvalidatedRefSCCs;
255-
256248
/// The set of invalidated SCCs which should be skipped if they are found
257249
/// in \c CWorklist.
258250
///

llvm/lib/Analysis/CGSCCPassManager.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,8 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
150150
SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;
151151
SmallPriorityWorklist<LazyCallGraph::SCC *, 1> CWorklist;
152152

153-
// Keep sets for invalidated SCCs and RefSCCs that should be skipped when
153+
// Keep sets for invalidated SCCs that should be skipped when
154154
// iterating off the worklists.
155-
SmallPtrSet<LazyCallGraph::RefSCC *, 4> InvalidRefSCCSet;
156155
SmallPtrSet<LazyCallGraph::SCC *, 4> InvalidSCCSet;
157156

158157
SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
@@ -161,7 +160,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
161160
SmallVector<Function *, 4> DeadFunctions;
162161

163162
CGSCCUpdateResult UR = {CWorklist,
164-
InvalidRefSCCSet,
165163
InvalidSCCSet,
166164
nullptr,
167165
PreservedAnalyses::all(),
@@ -194,11 +192,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
194192

195193
do {
196194
LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();
197-
if (InvalidRefSCCSet.count(RC)) {
198-
LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
199-
continue;
200-
}
201-
202195
assert(CWorklist.empty() &&
203196
"Should always start with an empty SCC worklist");
204197

@@ -1172,7 +1165,6 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
11721165
}
11731166

11741167
assert(!UR.InvalidatedSCCs.count(C) && "Invalidated the current SCC!");
1175-
assert(!UR.InvalidatedRefSCCs.count(RC) && "Invalidated the current RefSCC!");
11761168
assert(&C->getOuterRefSCC() == RC && "Current SCC not in current RefSCC!");
11771169

11781170
// Record the current SCC for higher layers of the CGSCC pass manager now that

llvm/lib/Transforms/Utils/CallGraphUpdater.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,14 @@ bool CallGraphUpdater::finalize() {
5959
auto *DeadSCC = LCG->lookupSCC(N);
6060
assert(DeadSCC && DeadSCC->size() == 1 &&
6161
&DeadSCC->begin()->getFunction() == DeadFn);
62-
auto &DeadRC = DeadSCC->getOuterRefSCC();
6362

64-
FunctionAnalysisManager &FAM =
65-
AM->getResult<FunctionAnalysisManagerCGSCCProxy>(*DeadSCC, *LCG)
66-
.getManager();
67-
68-
FAM.clear(*DeadFn, DeadFn->getName());
63+
FAM->clear(*DeadFn, DeadFn->getName());
6964
AM->clear(*DeadSCC, DeadSCC->getName());
7065
LCG->markDeadFunction(*DeadFn);
7166

7267
// Mark the relevant parts of the call graph as invalid so we don't
7368
// visit them.
74-
UR->InvalidatedSCCs.insert(DeadSCC);
75-
UR->InvalidatedRefSCCs.insert(&DeadRC);
69+
UR->InvalidatedSCCs.insert(LCG->lookupSCC(N));
7670
UR->DeadFunctions.push_back(DeadFn);
7771
} else {
7872
// The CGSCC infrastructure batch deletes functions at the end of the

llvm/unittests/Analysis/CGSCCPassManagerTest.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,61 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions2) {
18781878
ASSERT_TRUE(Ran);
18791879
}
18801880

1881+
TEST_F(CGSCCPassManagerTest, TestDeletionOfFunctionInNonTrivialRefSCC) {
1882+
std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
1883+
"entry:\n"
1884+
" call void @f2()\n"
1885+
" ret void\n"
1886+
"}\n"
1887+
"define void @f2() {\n"
1888+
"entry:\n"
1889+
" call void @f1()\n"
1890+
" ret void\n"
1891+
"}\n");
1892+
1893+
bool Ran = false;
1894+
CGSCCPassManager CGPM;
1895+
CGPM.addPass(LambdaSCCPassNoPreserve(
1896+
[&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
1897+
CGSCCUpdateResult &UR) {
1898+
if (Ran)
1899+
return;
1900+
1901+
LazyCallGraph::Node *N1 = nullptr;
1902+
1903+
for (LazyCallGraph::Node *N : SCCNodes(C)) {
1904+
Function &F = N->getFunction();
1905+
if (F.getName() != "f1")
1906+
continue;
1907+
N1 = N;
1908+
1909+
Function &F2 = *F.getParent()->getFunction("f2");
1910+
1911+
// Remove f1 <-> f2 references
1912+
F.getEntryBlock().front().eraseFromParent();
1913+
F2.getEntryBlock().front().eraseFromParent();
1914+
1915+
CallGraphUpdater CGU;
1916+
CGU.initialize(CG, C, AM, UR);
1917+
CGU.removeFunction(F2);
1918+
CGU.reanalyzeFunction(F);
1919+
1920+
Ran = true;
1921+
}
1922+
1923+
// Check that updateCGAndAnalysisManagerForCGSCCPass() after
1924+
// CallGraphUpdater::removeFunction() succeeds.
1925+
updateCGAndAnalysisManagerForCGSCCPass(CG, *CG.lookupSCC(*N1), *N1, AM,
1926+
UR, FAM);
1927+
}));
1928+
1929+
ModulePassManager MPM;
1930+
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
1931+
MPM.run(*M, MAM);
1932+
1933+
ASSERT_TRUE(Ran);
1934+
}
1935+
18811936
TEST_F(CGSCCPassManagerTest, TestInsertionOfNewNonTrivialCallEdge) {
18821937
std::unique_ptr<Module> M = parseIR("define void @f1() {\n"
18831938
"entry:\n"

0 commit comments

Comments
 (0)