Skip to content

Commit a866a0a

Browse files
committed
[Inliner] Handle CGSCC changes from llvm#94815
With llvm#94815, the nodes belonging to dead functions are no longer invalidated, but kept around to batch delete at the end of the call graph walk. The ML inliner needs to be updated to handle this. This fixes some asserts getting hit, e.g. https://crbug.com/348376263.
1 parent 826bde5 commit a866a0a

File tree

2 files changed

+23
-24
lines changed

2 files changed

+23
-24
lines changed

llvm/lib/Analysis/MLInlineAdvisor.cpp

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ unsigned MLInlineAdvisor::getInitialFunctionLevel(const Function &F) const {
187187
return CG.lookup(F) ? FunctionLevels.at(CG.lookup(F)) : 0;
188188
}
189189

190-
void MLInlineAdvisor::onPassEntry(LazyCallGraph::SCC *LastSCC) {
191-
if (!LastSCC || ForceStop)
190+
void MLInlineAdvisor::onPassEntry(LazyCallGraph::SCC *CurSCC) {
191+
if (!CurSCC || ForceStop)
192192
return;
193193
FPICache.clear();
194194
// Function passes executed between InlinerPass runs may have changed the
@@ -206,23 +206,18 @@ void MLInlineAdvisor::onPassEntry(LazyCallGraph::SCC *LastSCC) {
206206
// care about the nature of the Edge (call or ref). `FunctionLevels`-wise, we
207207
// record them at the same level as the original node (this is a choice, may
208208
// need revisiting).
209-
NodeCount -= static_cast<int64_t>(NodesInLastSCC.size());
210209
while (!NodesInLastSCC.empty()) {
211210
const auto *N = *NodesInLastSCC.begin();
211+
assert(!N->isDead());
212212
NodesInLastSCC.erase(N);
213-
// The Function wrapped by N could have been deleted since we last saw it.
214-
if (N->isDead()) {
215-
assert(!N->getFunction().isDeclaration());
216-
continue;
217-
}
218-
++NodeCount;
219213
EdgeCount += getLocalCalls(N->getFunction());
220214
const auto NLevel = FunctionLevels.at(N);
221215
for (const auto &E : *(*N)) {
222216
const auto *AdjNode = &E.getNode();
223217
assert(!AdjNode->isDead() && !AdjNode->getFunction().isDeclaration());
224218
auto I = AllNodes.insert(AdjNode);
225219
if (I.second) {
220+
++NodeCount;
226221
NodesInLastSCC.insert(AdjNode);
227222
FunctionLevels[AdjNode] = NLevel;
228223
}
@@ -235,31 +230,29 @@ void MLInlineAdvisor::onPassEntry(LazyCallGraph::SCC *LastSCC) {
235230
// (Re)use NodesInLastSCC to remember the nodes in the SCC right now,
236231
// in case the SCC is split before onPassExit and some nodes are split out
237232
assert(NodesInLastSCC.empty());
238-
for (const auto &N : *LastSCC)
233+
for (const auto &N : *CurSCC)
239234
NodesInLastSCC.insert(&N);
240235
}
241236

242-
void MLInlineAdvisor::onPassExit(LazyCallGraph::SCC *LastSCC) {
237+
void MLInlineAdvisor::onPassExit(LazyCallGraph::SCC *CurSCC) {
243238
// No need to keep this around - function passes will invalidate it.
244239
if (!KeepFPICache)
245240
FPICache.clear();
246-
if (!LastSCC || ForceStop)
241+
if (!CurSCC || ForceStop)
247242
return;
248243
// Keep track of the nodes and edges we last saw. Then, in onPassEntry,
249244
// we update the node count and edge count from the subset of these nodes that
250245
// survived.
251246
EdgesOfLastSeenNodes = 0;
252247

253248
// Check on nodes that were in SCC onPassEntry
254-
for (auto I = NodesInLastSCC.begin(); I != NodesInLastSCC.end();) {
255-
if ((*I)->isDead())
256-
NodesInLastSCC.erase(*I++);
257-
else
258-
EdgesOfLastSeenNodes += getLocalCalls((*I++)->getFunction());
249+
for (const LazyCallGraph::Node *N : NodesInLastSCC) {
250+
assert(!N->isDead());
251+
EdgesOfLastSeenNodes += getLocalCalls(N->getFunction());
259252
}
260253

261254
// Check on nodes that may have got added to SCC
262-
for (const auto &N : *LastSCC) {
255+
for (const auto &N : *CurSCC) {
263256
assert(!N.isDead());
264257
auto I = NodesInLastSCC.insert(&N);
265258
if (I.second)
@@ -306,11 +299,18 @@ void MLInlineAdvisor::onSuccessfulInlining(const MLInlineAdvice &Advice,
306299
int64_t NewCallerAndCalleeEdges =
307300
getCachedFPI(*Caller).DirectCallsToDefinedFunctions;
308301

309-
if (CalleeWasDeleted)
302+
// A dead function's node is not actually removed from the call graph until
303+
// the end of the call graph walk, but the node no longer belongs to any valid
304+
// SCC.
305+
if (CalleeWasDeleted) {
310306
--NodeCount;
311-
else
307+
LazyCallGraph::Node *CalleeN = CG.lookup(*Callee);
308+
NodesInLastSCC.erase(CalleeN);
309+
AllNodes.erase(CalleeN);
310+
} else {
312311
NewCallerAndCalleeEdges +=
313312
getCachedFPI(*Callee).DirectCallsToDefinedFunctions;
313+
}
314314
EdgeCount += (NewCallerAndCalleeEdges - Advice.CallerAndCalleeEdges);
315315
assert(CurrentIRSize >= 0 && EdgeCount >= 0 && NodeCount >= 0);
316316
}
@@ -484,8 +484,7 @@ void MLInlineAdvisor::print(raw_ostream &OS) const {
484484
OS << "\n";
485485
OS << "[MLInlineAdvisor] FuncLevels:\n";
486486
for (auto I : FunctionLevels)
487-
OS << (I.first->isDead() ? "<deleted>" : I.first->getFunction().getName())
488-
<< " : " << I.second << "\n";
487+
OS << I.first->getFunction().getName() << " : " << I.second << "\n";
489488

490489
OS << "\n";
491490
}

llvm/lib/Transforms/IPO/Inliner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
223223
InlineAdvisor &Advisor = getAdvisor(MAMProxy, FAM, M);
224224
Advisor.onPassEntry(&InitialC);
225225

226-
auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(&InitialC); });
227-
228226
// We use a single common worklist for calls across the entire SCC. We
229227
// process these in-order and append new calls introduced during inlining to
230228
// the end. The PriorityInlineOrder is optional here, in which the smaller
@@ -564,6 +562,8 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
564562
++NumDeleted;
565563
}
566564

565+
Advisor.onPassExit(C);
566+
567567
if (!Changed)
568568
return PreservedAnalyses::all();
569569

0 commit comments

Comments
 (0)