Skip to content

Commit 4e2cc6a

Browse files
aeubanksanton-bannykh
authored andcommitted
[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. (cherry picked from commit 8d800e6)
1 parent cb1390a commit 4e2cc6a

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
@@ -152,9 +152,8 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
152152
SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;
153153
SmallPriorityWorklist<LazyCallGraph::SCC *, 1> CWorklist;
154154

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

160159
SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
@@ -163,7 +162,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
163162
SmallVector<Function *, 4> DeadFunctions;
164163

165164
CGSCCUpdateResult UR = {CWorklist,
166-
InvalidRefSCCSet,
167165
InvalidSCCSet,
168166
nullptr,
169167
PreservedAnalyses::all(),
@@ -196,11 +194,6 @@ ModuleToPostOrderCGSCCPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) {
196194

197195
do {
198196
LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();
199-
if (InvalidRefSCCSet.count(RC)) {
200-
LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
201-
continue;
202-
}
203-
204197
assert(CWorklist.empty() &&
205198
"Should always start with an empty SCC worklist");
206199

@@ -1179,7 +1172,6 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
11791172
}
11801173

11811174
assert(!UR.InvalidatedSCCs.count(C) && "Invalidated the current SCC!");
1182-
assert(!UR.InvalidatedRefSCCs.count(RC) && "Invalidated the current RefSCC!");
11831175
assert(&C->getOuterRefSCC() == RC && "Current SCC not in current RefSCC!");
11841176

11851177
// 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
@@ -1875,6 +1875,61 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewFunctions2) {
18751875
ASSERT_TRUE(Ran);
18761876
}
18771877

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

0 commit comments

Comments
 (0)