Skip to content

Commit cc65f3e

Browse files
committed
[GlobalOpt] Preserve CFG analyses
The only place we modify the CFG is when calling removeUnreachableBlocks(), so insert a callback there which invalidates analyses for that function (or recomputes DT in the legacy PM). Small compile time wins across the board: https://llvm-compile-time-tracker.com/compare.php?from=f444ea8ce0aaaa5ec1a4129809389da15cc41396&to=698f41f4fc26cbf1006ed5d88e9d658edfc5b749&stat=instructions Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D128145
1 parent 314dbde commit cc65f3e

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

llvm/lib/Transforms/IPO/GlobalOpt.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,7 +1941,8 @@ OptimizeFunctions(Module &M,
19411941
function_ref<TargetTransformInfo &(Function &)> GetTTI,
19421942
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
19431943
function_ref<DominatorTree &(Function &)> LookupDomTree,
1944-
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats) {
1944+
SmallPtrSetImpl<const Comdat *> &NotDiscardableComdats,
1945+
function_ref<void(Function &F)> ChangedCFGCallback) {
19451946

19461947
bool Changed = false;
19471948

@@ -1974,13 +1975,11 @@ OptimizeFunctions(Module &M,
19741975
// So, remove unreachable blocks from the function, because a) there's
19751976
// no point in analyzing them and b) GlobalOpt should otherwise grow
19761977
// some more complicated logic to break these cycles.
1977-
// Removing unreachable blocks might invalidate the dominator so we
1978-
// recalculate it.
1978+
// Notify the analysis manager that we've modified the function's CFG.
19791979
if (!F.isDeclaration()) {
19801980
if (removeUnreachableBlocks(F)) {
1981-
auto &DT = LookupDomTree(F);
1982-
DT.recalculate(F);
19831981
Changed = true;
1982+
ChangedCFGCallback(F);
19841983
}
19851984
}
19861985

@@ -2443,12 +2442,13 @@ static bool OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn) {
24432442
return Changed;
24442443
}
24452444

2446-
static bool optimizeGlobalsInModule(
2447-
Module &M, const DataLayout &DL,
2448-
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
2449-
function_ref<TargetTransformInfo &(Function &)> GetTTI,
2450-
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2451-
function_ref<DominatorTree &(Function &)> LookupDomTree) {
2445+
static bool
2446+
optimizeGlobalsInModule(Module &M, const DataLayout &DL,
2447+
function_ref<TargetLibraryInfo &(Function &)> GetTLI,
2448+
function_ref<TargetTransformInfo &(Function &)> GetTTI,
2449+
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2450+
function_ref<DominatorTree &(Function &)> LookupDomTree,
2451+
function_ref<void(Function &F)> ChangedCFGCallback) {
24522452
SmallPtrSet<const Comdat *, 8> NotDiscardableComdats;
24532453
bool Changed = false;
24542454
bool LocalChange = true;
@@ -2473,7 +2473,7 @@ static bool optimizeGlobalsInModule(
24732473

24742474
// Delete functions that are trivially dead, ccc -> fastcc
24752475
LocalChange |= OptimizeFunctions(M, GetTLI, GetTTI, GetBFI, LookupDomTree,
2476-
NotDiscardableComdats);
2476+
NotDiscardableComdats, ChangedCFGCallback);
24772477

24782478
// Optimize global_ctors list.
24792479
LocalChange |=
@@ -2526,10 +2526,22 @@ PreservedAnalyses GlobalOptPass::run(Module &M, ModuleAnalysisManager &AM) {
25262526
auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
25272527
return FAM.getResult<BlockFrequencyAnalysis>(F);
25282528
};
2529+
auto ChangedCFGCallback = [&FAM](Function &F) {
2530+
FAM.invalidate(F, PreservedAnalyses::none());
2531+
};
25292532

2530-
if (!optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree))
2533+
if (!optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree,
2534+
ChangedCFGCallback))
25312535
return PreservedAnalyses::all();
2532-
return PreservedAnalyses::none();
2536+
2537+
PreservedAnalyses PA = PreservedAnalyses::none();
2538+
// We have not removed or replaced any functions.
2539+
PA.preserve<FunctionAnalysisManagerModuleProxy>();
2540+
// The only place we modify the CFG is when calling
2541+
// removeUnreachableBlocks(), but there we make sure to invalidate analyses
2542+
// for modified functions.
2543+
PA.preserveSet<CFGAnalyses>();
2544+
return PA;
25332545
}
25342546

25352547
namespace {
@@ -2560,8 +2572,13 @@ struct GlobalOptLegacyPass : public ModulePass {
25602572
return this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
25612573
};
25622574

2563-
return optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI,
2564-
LookupDomTree);
2575+
auto ChangedCFGCallback = [&LookupDomTree](Function &F) {
2576+
auto &DT = LookupDomTree(F);
2577+
DT.recalculate(F);
2578+
};
2579+
2580+
return optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree,
2581+
ChangedCFGCallback);
25652582
}
25662583

25672584
void getAnalysisUsage(AnalysisUsage &AU) const override {

0 commit comments

Comments
 (0)