Index: include/llvm/Transforms/Utils/Local.h =================================================================== --- include/llvm/Transforms/Utils/Local.h +++ include/llvm/Transforms/Utils/Local.h @@ -345,6 +345,9 @@ /// Returns true if any basic block was removed. bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr); +bool removeUnreachable(Function &F, DominatorTree &DT, + LazyValueInfo *LVI = nullptr); + /// Combine the metadata of two instructions so that K can replace J /// /// Metadata not listed as known via KnownIDs is removed Index: lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- lib/Transforms/IPO/GlobalOpt.cpp +++ lib/Transforms/IPO/GlobalOpt.cpp @@ -2034,14 +2034,10 @@ // 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. if (!F->isDeclaration()) { - if (removeUnreachableBlocks(*F)) { - auto &DT = LookupDomTree(*F); - DT.recalculate(*F); + auto &DT = LookupDomTree(*F); + if (removeUnreachable(*F, DT)) Changed = true; - } } Changed |= processGlobal(*F, TLI, LookupDomTree); Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -1700,6 +1701,51 @@ return true; } +bool llvm::removeUnreachable(Function &F, DominatorTree &DT, + LazyValueInfo *LVI) { + ReversePostOrderTraversal RPOT(&F); + SmallPtrSet Live; + SmallPtrSet Processed; + + for (BasicBlock *BB : RPOT) + Live.insert(BB); + + if (Live.size() == F.size()) + return false; + + SmallVector Worklist; + for (BasicBlock &BB : F) { + if (!Live.count(&BB)) + Worklist.push_back(&BB); + } + + while (!Worklist.empty()) { + BasicBlock *BB = Worklist.pop_back_val(); + if (Processed.count(BB)) + continue; + auto *N = DT.getNode(BB); + if (!N) { + if (LVI) + LVI->eraseBlock(BB); + BB->dropAllReferences(); + BB->eraseFromParent(); + continue; + } + for (auto *DTN : post_order(N)) { + BasicBlock *DTBlock = DTN->getBlock(); + Processed.insert(DTBlock); + for (BasicBlock *Succ : successors(DTBlock)) + Succ->removePredecessor(DTBlock); + if (LVI) + LVI->eraseBlock(DTBlock); + DT.eraseNode(DTBlock); + DTBlock->dropAllReferences(); + DTBlock->eraseFromParent(); + } + } + return true; +} + void llvm::combineMetadata(Instruction *K, const Instruction *J, ArrayRef KnownIDs) { SmallVector, 4> Metadata; Index: test/Other/new-pm-lto-defaults.ll =================================================================== --- test/Other/new-pm-lto-defaults.ll +++ test/Other/new-pm-lto-defaults.ll @@ -40,8 +40,8 @@ ; CHECK-O-NEXT: Running pass: GlobalSplitPass ; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass ; CHECK-O2-NEXT: Running pass: GlobalOptPass -; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PromotePass> ; CHECK-O2-NEXT: Running analysis: DominatorTreeAnalysis +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PromotePass> ; CHECK-O2-NEXT: Running analysis: AssumptionAnalysis ; CHECK-O2-NEXT: Running pass: ConstantMergePass ; CHECK-O2-NEXT: Running pass: DeadArgumentEliminationPass