diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1941,7 +1941,8 @@ function_ref GetTTI, function_ref GetBFI, function_ref LookupDomTree, - SmallPtrSetImpl &NotDiscardableComdats) { + SmallPtrSetImpl &NotDiscardableComdats, + function_ref ChangedCFGCallback) { bool Changed = false; @@ -1974,13 +1975,11 @@ // So, remove unreachable blocks from the function, because a) there's // no point in analyzing them and b) GlobalOpt should otherwise grow // some more complicated logic to break these cycles. - // Removing unreachable blocks might invalidate the dominator so we - // recalculate it. + // Notify the analysis manager that we've modified the function's CFG. if (!F.isDeclaration()) { if (removeUnreachableBlocks(F)) { - auto &DT = LookupDomTree(F); - DT.recalculate(F); Changed = true; + ChangedCFGCallback(F); } } @@ -2443,12 +2442,13 @@ return Changed; } -static bool optimizeGlobalsInModule( - Module &M, const DataLayout &DL, - function_ref GetTLI, - function_ref GetTTI, - function_ref GetBFI, - function_ref LookupDomTree) { +static bool +optimizeGlobalsInModule(Module &M, const DataLayout &DL, + function_ref GetTLI, + function_ref GetTTI, + function_ref GetBFI, + function_ref LookupDomTree, + function_ref ChangedCFGCallback) { SmallPtrSet NotDiscardableComdats; bool Changed = false; bool LocalChange = true; @@ -2473,7 +2473,7 @@ // Delete functions that are trivially dead, ccc -> fastcc LocalChange |= OptimizeFunctions(M, GetTLI, GetTTI, GetBFI, LookupDomTree, - NotDiscardableComdats); + NotDiscardableComdats, ChangedCFGCallback); // Optimize global_ctors list. LocalChange |= @@ -2526,10 +2526,22 @@ auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & { return FAM.getResult(F); }; + auto ChangedCFGCallback = [&FAM](Function &F) { + FAM.invalidate(F, PreservedAnalyses::none()); + }; - if (!optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree)) + if (!optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree, + ChangedCFGCallback)) return PreservedAnalyses::all(); - return PreservedAnalyses::none(); + + PreservedAnalyses PA = PreservedAnalyses::none(); + // We have not removed or replaced any functions. + PA.preserve(); + // The only place we modify the CFG is when calling + // removeUnreachableBlocks(), but there we make sure to invalidate analyses + // for modified functions. + PA.preserveSet(); + return PA; } namespace { @@ -2560,8 +2572,13 @@ return this->getAnalysis(F).getBFI(); }; - return optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, - LookupDomTree); + auto ChangedCFGCallback = [&LookupDomTree](Function &F) { + auto &DT = LookupDomTree(F); + DT.recalculate(F); + }; + + return optimizeGlobalsInModule(M, DL, GetTLI, GetTTI, GetBFI, LookupDomTree, + ChangedCFGCallback); } void getAnalysisUsage(AnalysisUsage &AU) const override {