Skip to content

Commit a2a5508

Browse files
authored
[nfc][mlgo] Incrementally update DominatorTreeAnalysis in FunctionPropertiesAnalysis (#104867)
We need the dominator tree analysis for loop info analysis, which we need to get features like most nested loop and number of top level loops. Invalidating and recomputing these from scratch after each successful inlining can sometimes lead to lengthy compile times. We don't need to recompute from scratch, though, since we have some boundary information about where the changes to the CFG happen; moreover, for dom tree, the API supports incrementally updating the analysis result. This change addresses the dom tree part. The loop info is still recomputed from scratch. This does reduce the compile time quite significantly already, though (~5x in a specific case) The loop info change might be more involved and would follow in a subsequent PR.
1 parent 8b4147d commit a2a5508

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H
1616

1717
#include "llvm/ADT/DenseSet.h"
18+
#include "llvm/IR/Dominators.h"
1819
#include "llvm/IR/PassManager.h"
1920

2021
namespace llvm {
@@ -186,7 +187,12 @@ class FunctionPropertiesUpdater {
186187
static bool isUpdateValid(Function &F, const FunctionPropertiesInfo &FPI,
187188
FunctionAnalysisManager &FAM);
188189

190+
DominatorTree &getUpdatedDominatorTree(FunctionAnalysisManager &FAM) const;
191+
189192
DenseSet<const BasicBlock *> Successors;
193+
194+
// Edges we might potentially need to remove from the dominator tree.
195+
SmallVector<DominatorTree::UpdateType, 2> DomTreeUpdates;
190196
};
191197
} // namespace llvm
192198
#endif // LLVM_ANALYSIS_FUNCTIONPROPERTIESANALYSIS_H

llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,14 @@ FunctionPropertiesUpdater::FunctionPropertiesUpdater(
326326
// with the CB BB ('Entry') between which the inlined callee will be pasted.
327327
Successors.insert(succ_begin(&CallSiteBB), succ_end(&CallSiteBB));
328328

329+
// the outcome of the inlining may be that some edges get lost (DCEd BBs
330+
// because inlining brought some constant, for example). We don't know which
331+
// edges will be removed, so we list all of them as potentially removable.
332+
for (auto *Succ : successors(&CallSiteBB))
333+
DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,
334+
const_cast<BasicBlock *>(&CallSiteBB),
335+
const_cast<BasicBlock *>(Succ));
336+
329337
// Inlining only handles invoke and calls. If this is an invoke, and inlining
330338
// it pulls another invoke, the original landing pad may get split, so as to
331339
// share its content with other potential users. So the edge up to which we
@@ -336,6 +344,11 @@ FunctionPropertiesUpdater::FunctionPropertiesUpdater(
336344
if (const auto *II = dyn_cast<InvokeInst>(&CB)) {
337345
const auto *UnwindDest = II->getUnwindDest();
338346
Successors.insert(succ_begin(UnwindDest), succ_end(UnwindDest));
347+
// Same idea as above, we pretend we lose all these edges.
348+
for (auto *Succ : successors(UnwindDest))
349+
DomTreeUpdates.emplace_back(DominatorTree::UpdateKind::Delete,
350+
const_cast<BasicBlock *>(UnwindDest),
351+
const_cast<BasicBlock *>(Succ));
339352
}
340353

341354
// Exclude the CallSiteBB, if it happens to be its own successor (1-BB loop).
@@ -356,6 +369,45 @@ FunctionPropertiesUpdater::FunctionPropertiesUpdater(
356369
FPI.updateForBB(*BB, -1);
357370
}
358371

372+
DominatorTree &FunctionPropertiesUpdater::getUpdatedDominatorTree(
373+
FunctionAnalysisManager &FAM) const {
374+
auto &DT =
375+
FAM.getResult<DominatorTreeAnalysis>(const_cast<Function &>(Caller));
376+
377+
SetVector<const BasicBlock *> NewSucc;
378+
NewSucc.insert(succ_begin(&CallSiteBB), succ_end(&CallSiteBB));
379+
380+
// tell the DomTree about the new edges
381+
std::deque<const BasicBlock *> Worklist;
382+
Worklist.push_back(&CallSiteBB);
383+
384+
// Build the list of edges to actually remove. Those are those edges in the
385+
// DomTreeUpdates that cannot be found in the CFG anymore.
386+
SmallVector<DominatorTree::UpdateType, 2> FinalDomTreeUpdates;
387+
while (!Worklist.empty()) {
388+
auto *BB = Worklist.front();
389+
Worklist.pop_front();
390+
assert(DT.getNode(BB));
391+
392+
for (auto *Succ : NewSucc) {
393+
if (!DT.getNode(Succ))
394+
Worklist.push_back(Succ);
395+
FinalDomTreeUpdates.push_back({DominatorTree::UpdateKind::Insert,
396+
const_cast<BasicBlock *>(BB),
397+
const_cast<BasicBlock *>(Succ)});
398+
}
399+
}
400+
for (auto &Upd : DomTreeUpdates)
401+
if (!llvm::is_contained(successors(Upd.getFrom()), Upd.getTo()))
402+
FinalDomTreeUpdates.push_back(Upd);
403+
404+
DT.applyUpdates(FinalDomTreeUpdates);
405+
#ifdef EXPENSIVE_CHECKS
406+
assert(DT.verify(DominatorTree::VerificationLevel::Full));
407+
#endif
408+
return DT;
409+
}
410+
359411
void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
360412
// Update feature values from the BBs that were copied from the callee, or
361413
// might have been modified because of inlining. The latter have been
@@ -383,8 +435,7 @@ void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
383435
// remove E.
384436
SetVector<const BasicBlock *> Reinclude;
385437
SetVector<const BasicBlock *> Unreachable;
386-
const auto &DT =
387-
FAM.getResult<DominatorTreeAnalysis>(const_cast<Function &>(Caller));
438+
auto &DT = getUpdatedDominatorTree(FAM);
388439

389440
if (&CallSiteBB != &*Caller.begin())
390441
Reinclude.insert(&*Caller.begin());
@@ -427,6 +478,9 @@ void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
427478

428479
const auto &LI = FAM.getResult<LoopAnalysis>(const_cast<Function &>(Caller));
429480
FPI.updateAggregateStats(Caller, LI);
481+
#ifdef EXPENSIVE_CHECKS
482+
assert(isUpdateValid(Caller, FPI, FAM));
483+
#endif
430484
}
431485

432486
bool FunctionPropertiesUpdater::isUpdateValid(Function &F,

llvm/lib/Analysis/MLInlineAdvisor.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ void MLInlineAdvisor::onSuccessfulInlining(const MLInlineAdvice &Advice,
288288
{
289289
PreservedAnalyses PA = PreservedAnalyses::all();
290290
PA.abandon<FunctionPropertiesAnalysis>();
291-
PA.abandon<DominatorTreeAnalysis>();
292291
PA.abandon<LoopAnalysis>();
293292
FAM.invalidate(*Caller, PA);
294293
}

0 commit comments

Comments
 (0)