Skip to content

Commit f267880

Browse files
committed
Reapply "[nfc][mlgo] Incrementally update DominatorTreeAnalysis in FunctionPropertiesAnalysis (#104867)
Reverts c992690.
1 parent 73c3b73 commit f267880

File tree

4 files changed

+121
-3
lines changed

4 files changed

+121
-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: 48 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,37 @@ 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+
SmallVector<DominatorTree::UpdateType, 2> FinalDomTreeUpdates;
378+
379+
// When constructing the updater, we pesimistically went through all the
380+
// successors of the callsite BB and prepared them for removal, but not all
381+
// may actually end up being removed. Check which actually survived.
382+
// Conversely, we won't re-add them if they weren't removed.
383+
DenseSet<const BasicBlock *> NewSuccessors;
384+
NewSuccessors.insert(succ_begin(&CallSiteBB), succ_end(&CallSiteBB));
385+
for (auto &Upd : DomTreeUpdates)
386+
if (Upd.getFrom() != &CallSiteBB || !NewSuccessors.contains(Upd.getTo()))
387+
FinalDomTreeUpdates.push_back(Upd);
388+
389+
DenseSet<const BasicBlock *> Inserted;
390+
for (auto *Succ : successors(&CallSiteBB))
391+
if (Inserted.insert(Succ).second && !NewSuccessors.contains(Succ))
392+
FinalDomTreeUpdates.push_back({DominatorTree::UpdateKind::Insert,
393+
const_cast<BasicBlock *>(&CallSiteBB),
394+
const_cast<BasicBlock *>(Succ)});
395+
396+
DT.applyUpdates(FinalDomTreeUpdates);
397+
#ifdef EXPENSIVE_CHECKS
398+
assert(DT.verify(DominatorTree::VerificationLevel::Full));
399+
#endif
400+
return DT;
401+
}
402+
359403
void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
360404
// Update feature values from the BBs that were copied from the callee, or
361405
// might have been modified because of inlining. The latter have been
@@ -383,8 +427,7 @@ void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
383427
// remove E.
384428
SetVector<const BasicBlock *> Reinclude;
385429
SetVector<const BasicBlock *> Unreachable;
386-
const auto &DT =
387-
FAM.getResult<DominatorTreeAnalysis>(const_cast<Function &>(Caller));
430+
auto &DT = getUpdatedDominatorTree(FAM);
388431

389432
if (&CallSiteBB != &*Caller.begin())
390433
Reinclude.insert(&*Caller.begin());
@@ -427,6 +470,9 @@ void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
427470

428471
const auto &LI = FAM.getResult<LoopAnalysis>(const_cast<Function &>(Caller));
429472
FPI.updateAggregateStats(Caller, LI);
473+
#ifdef EXPENSIVE_CHECKS
474+
assert(isUpdateValid(Caller, FPI, FAM));
475+
#endif
430476
}
431477

432478
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
}

llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,4 +999,71 @@ declare <4 x ptr> @f4()
999999
EXPECT_EQ(DetailedF1Properties.CallReturnsVectorPointerCount, 1);
10001000
EnableDetailedFunctionProperties.setValue(false);
10011001
}
1002+
1003+
TEST_F(FunctionPropertiesAnalysisTest, ReAddEdges) {
1004+
LLVMContext C;
1005+
std::unique_ptr<Module> M = makeLLVMModule(C, R"IR(
1006+
define hidden void @f1(ptr noundef %destatep, i32 noundef %offset, i8 noundef zeroext %byte1) {
1007+
entry:
1008+
%cmp = icmp eq i8 %byte1, 0
1009+
br i1 %cmp, label %if.then, label %if.else
1010+
1011+
if.then: ; preds = %entry
1012+
call fastcc void @f2(ptr noundef %destatep, i32 noundef 37, i32 noundef 600)
1013+
%and = and i32 %offset, 3
1014+
switch i32 %and, label %default.unreachable [
1015+
i32 0, label %sw.bb
1016+
i32 1, label %sw.bb1
1017+
i32 2, label %sw.bb1
1018+
i32 3, label %if.end
1019+
]
1020+
1021+
sw.bb: ; preds = %if.then
1022+
call fastcc void @f2(ptr noundef %destatep, i32 noundef 57, i32 noundef 600)
1023+
br label %if.end
1024+
1025+
sw.bb1: ; preds = %if.then, %if.then
1026+
call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600) #34
1027+
br label %if.end
1028+
1029+
default.unreachable: ; preds = %if.then
1030+
unreachable
1031+
1032+
if.else: ; preds = %entry
1033+
call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600)
1034+
br label %if.end
1035+
1036+
if.end: ; preds = %sw.bb, %sw.bb1, %if.then, %if.else
1037+
ret void
1038+
}
1039+
1040+
define internal fastcc void @f2(ptr nocapture noundef %destatep, i32 noundef %r_enc, i32 noundef %whack) {
1041+
entry:
1042+
%enc_prob = getelementptr inbounds nuw i8, ptr %destatep, i32 512
1043+
%arrayidx = getelementptr inbounds [67 x i32], ptr %enc_prob, i32 0, i32 %r_enc
1044+
%0 = load i32, ptr %arrayidx, align 4
1045+
%sub = sub nsw i32 %0, %whack
1046+
store i32 %sub, ptr %arrayidx, align 4
1047+
ret void
1048+
}
1049+
)IR");
1050+
auto *F1 = M->getFunction("f1");
1051+
auto *F2 = M->getFunction("f2");
1052+
auto *CB = [&]() -> CallBase * {
1053+
for (auto &BB : *F1)
1054+
for (auto &I : BB)
1055+
if (auto *CB = dyn_cast<CallBase>(&I);
1056+
CB && CB->getCalledFunction() && CB->getCalledFunction() == F2)
1057+
return CB;
1058+
return nullptr;
1059+
}();
1060+
ASSERT_NE(CB, nullptr);
1061+
auto FPI = buildFPI(*F1);
1062+
FunctionPropertiesUpdater FPU(FPI, *CB);
1063+
InlineFunctionInfo IFI;
1064+
auto IR = llvm::InlineFunction(*CB, IFI);
1065+
EXPECT_TRUE(IR.isSuccess());
1066+
invalidate(*F1);
1067+
EXPECT_TRUE(FPU.finishAndTest(FAM));
1068+
}
10021069
} // end anonymous namespace

0 commit comments

Comments
 (0)