Index: llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h +++ llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h @@ -23,6 +23,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/ValueHandle.h" #include #include @@ -34,7 +35,7 @@ class BranchInst; class CmpInst; class Constant; -class DeferredDominance; +class DomTreeUpdater; class Function; class Instruction; class IntrinsicInst; @@ -78,7 +79,7 @@ TargetLibraryInfo *TLI; LazyValueInfo *LVI; AliasAnalysis *AA; - DeferredDominance *DDT; + DomTreeUpdater *DTU; std::unique_ptr BFI; std::unique_ptr BPI; bool HasProfileData = false; @@ -109,8 +110,8 @@ // Glue for old PM. bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_, - AliasAnalysis *AA_, DeferredDominance *DDT_, - bool HasProfileData_, std::unique_ptr BFI_, + AliasAnalysis *AA_, DomTreeUpdater *DTU_, bool HasProfileData_, + std::unique_ptr BFI_, std::unique_ptr BPI_); PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); Index: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -20,6 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/InstrTypes.h" #include @@ -27,8 +28,8 @@ class BlockFrequencyInfo; class BranchProbabilityInfo; -class DeferredDominance; class DominatorTree; +class DomTreeUpdater; class Function; class Instruction; class LoopInfo; @@ -39,7 +40,7 @@ class Value; /// Delete the specified block, which must have no predecessors. -void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr); +void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); /// We know that BB has one predecessor. If there are any single-entry PHI nodes /// in it, fold them away. This handles the case when all entries to the PHI @@ -56,10 +57,9 @@ /// Attempts to merge a block into its predecessor, if possible. The return /// value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr, +bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU = nullptr, LoopInfo *LI = nullptr, - MemoryDependenceResults *MemDep = nullptr, - DeferredDominance *DDT = nullptr); + MemoryDependenceResults *MemDep = nullptr); /// Replace all uses of an instruction (specified by BI) with a value, then /// remove and delete the original instruction. Index: llvm/trunk/include/llvm/Transforms/Utils/Local.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/Local.h +++ llvm/trunk/include/llvm/Transforms/Utils/Local.h @@ -26,6 +26,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Operator.h" @@ -120,7 +121,7 @@ /// DeleteDeadConditions is true. bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false, const TargetLibraryInfo *TLI = nullptr, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); //===----------------------------------------------------------------------===// // Local dead code elimination. @@ -187,20 +188,19 @@ /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// BB is a block with one predecessor and its predecessor is known to have one /// successor (BB!). Eliminate the edge between them, moving the instructions in /// the predecessor into BB. This deletes the predecessor block. -void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr, - DeferredDominance *DDT = nullptr); +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); /// BB is known to contain an unconditional branch, and contains no instructions /// other than PHI nodes, potential debug intrinsics and the branch. If /// possible, eliminate BB by rewriting all the predecessors to branch to the /// successor block and return true. If we can't transform, return false. bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// Check for and eliminate duplicate PHI nodes in this block. This doesn't try /// to be clever about PHI nodes which differ only in the order of the incoming @@ -359,7 +359,7 @@ /// instruction, making it and the rest of the code in the block dead. unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, bool PreserveLCSSA = false, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// Convert the CallInst to InvokeInst with the specified unwind edge basic /// block. This also splits the basic block where CI is located, because @@ -374,13 +374,13 @@ /// /// \param BB Block whose terminator will be replaced. Its terminator must /// have an unwind successor. -void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr); +void removeUnwindEdge(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); /// Remove all blocks that can not be reached from the function's entry. /// /// Returns true if any basic block was removed. bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// Combine the metadata of two instructions so that K can replace J /// Index: llvm/trunk/lib/Transforms/Scalar/ADCE.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/ADCE.cpp +++ llvm/trunk/lib/Transforms/Scalar/ADCE.cpp @@ -30,9 +30,10 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" @@ -614,8 +615,8 @@ } } - DT.applyUpdates(DeletedEdges); - PDT.applyUpdates(DeletedEdges); + DomTreeUpdater(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager) + .applyUpdates(DeletedEdges); NumBranchesRemoved += 1; } Index: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -19,7 +19,6 @@ #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LazyValueInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" @@ -28,6 +27,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstrTypes.h" @@ -44,6 +44,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" #include #include @@ -308,6 +309,7 @@ /// a case fires on every incoming edge then the entire switch can be removed /// and replaced with a branch to the case destination. static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI, DominatorTree *DT) { + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy); Value *Cond = SI->getCondition(); BasicBlock *BB = SI->getParent(); @@ -372,7 +374,7 @@ ++NumDeadCases; Changed = true; if (--SuccessorsCount[Succ] == 0) - DT->deleteEdge(BB, Succ); + DTU.deleteEdge(BB, Succ); continue; } if (State == LazyValueInfo::True) { @@ -389,15 +391,11 @@ ++CI; } - if (Changed) { + if (Changed) // If the switch has been simplified to the point where it can be replaced // by a branch then do so now. - DeferredDominance DDT(*DT); ConstantFoldTerminator(BB, /*DeleteDeadConditions = */ false, - /*TLI = */ nullptr, &DDT); - DDT.flush(); - } - + /*TLI = */ nullptr, &DTU); return Changed; } Index: llvm/trunk/lib/Transforms/Scalar/GVN.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp @@ -38,7 +38,6 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PHITransAddr.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Attributes.h" @@ -48,6 +47,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -71,6 +71,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include "llvm/Transforms/Utils/VNCoercion.h" #include @@ -2028,12 +2029,13 @@ bool Changed = false; bool ShouldContinue = true; + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); // Merge unconditional branches, allowing PRE to catch more // optimization opportunities. for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ) { BasicBlock *BB = &*FI++; - bool removedBlock = MergeBlockIntoPredecessor(BB, DT, LI, MD); + bool removedBlock = MergeBlockIntoPredecessor(BB, &DTU, LI, MD); if (removedBlock) ++NumGVNBlocks; Index: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp @@ -30,7 +30,6 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" @@ -38,6 +37,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -65,6 +65,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include @@ -285,7 +286,7 @@ auto DT = &getAnalysis().getDomTree(); auto LVI = &getAnalysis().getLVI(); auto AA = &getAnalysis().getAAResults(); - DeferredDominance DDT(*DT); + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy); std::unique_ptr BFI; std::unique_ptr BPI; bool HasProfileData = F.hasProfileData(); @@ -295,7 +296,7 @@ BFI.reset(new BlockFrequencyInfo(F, *BPI, LI)); } - bool Changed = Impl.runImpl(F, TLI, LVI, AA, &DDT, HasProfileData, + bool Changed = Impl.runImpl(F, TLI, LVI, AA, &DTU, HasProfileData, std::move(BFI), std::move(BPI)); if (PrintLVIAfterJumpThreading) { dbgs() << "LVI for function '" << F.getName() << "':\n"; @@ -312,7 +313,7 @@ auto &DT = AM.getResult(F); auto &LVI = AM.getResult(F); auto &AA = AM.getResult(F); - DeferredDominance DDT(DT); + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); std::unique_ptr BFI; std::unique_ptr BPI; @@ -322,7 +323,7 @@ BFI.reset(new BlockFrequencyInfo(F, *BPI, LI)); } - bool Changed = runImpl(F, &TLI, &LVI, &AA, &DDT, HasProfileData, + bool Changed = runImpl(F, &TLI, &LVI, &AA, &DTU, HasProfileData, std::move(BFI), std::move(BPI)); if (!Changed) @@ -336,14 +337,14 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_, AliasAnalysis *AA_, - DeferredDominance *DDT_, bool HasProfileData_, + DomTreeUpdater *DTU_, bool HasProfileData_, std::unique_ptr BFI_, std::unique_ptr BPI_) { LLVM_DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n"); TLI = TLI_; LVI = LVI_; AA = AA_; - DDT = DDT_; + DTU = DTU_; BFI.reset(); BPI.reset(); // When profile data is available, we need to update edge weights after @@ -360,7 +361,9 @@ // JumpThreading must not processes blocks unreachable from entry. It's a // waste of compute time and can potentially lead to hangs. SmallPtrSet Unreachable; - DominatorTree &DT = DDT->flush(); + assert(DTU && "DTU isn't passed into JumpThreading before using it."); + assert(DTU->hasDomTree() && "JumpThreading relies on DomTree to proceed."); + DominatorTree &DT = DTU->getDomTree(); for (auto &BB : F) if (!DT.isReachableFromEntry(&BB)) Unreachable.insert(&BB); @@ -379,7 +382,7 @@ // Stop processing BB if it's the entry or is now deleted. The following // routines attempt to eliminate BB and locating a suitable replacement // for the entry is non-trivial. - if (&BB == &F.getEntryBlock() || DDT->pendingDeletedBB(&BB)) + if (&BB == &F.getEntryBlock() || DTU->isBBPendingDeletion(&BB)) continue; if (pred_empty(&BB)) { @@ -390,7 +393,7 @@ << '\n'); LoopHeaders.erase(&BB); LVI->eraseBlock(&BB); - DeleteDeadBlock(&BB, DDT); + DeleteDeadBlock(&BB, DTU); Changed = true; continue; } @@ -404,9 +407,9 @@ // Don't alter Loop headers and latches to ensure another pass can // detect and transform nested loops later. !LoopHeaders.count(&BB) && !LoopHeaders.count(BI->getSuccessor(0)) && - TryToSimplifyUncondBranchFromEmptyBlock(&BB, DDT)) { - // BB is valid for cleanup here because we passed in DDT. F remains - // BB's parent until a DDT->flush() event. + TryToSimplifyUncondBranchFromEmptyBlock(&BB, DTU)) { + // BB is valid for cleanup here because we passed in DTU. F remains + // BB's parent until a DTU->getDomTree() event. LVI->eraseBlock(&BB); Changed = true; } @@ -415,7 +418,8 @@ } while (Changed); LoopHeaders.clear(); - DDT->flush(); + // Flush only the Dominator Tree. + DTU->getDomTree(); LVI->enableDT(); return EverChanged; } @@ -609,7 +613,7 @@ // "X < 4" and "X < 3" is known true but "X < 4" itself is not available. // Perhaps getConstantOnEdge should be smart enough to do this? - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -626,7 +630,7 @@ /// If I is a PHI node, then we know the incoming values for any constants. if (PHINode *PN = dyn_cast(I)) { - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -759,7 +763,7 @@ const DataLayout &DL = PN->getModule()->getDataLayout(); // We can do this simplification if any comparisons fold to true or false. // See if any do. - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -806,7 +810,7 @@ if (!isa(CmpLHS) || cast(CmpLHS)->getParent() != BB) { - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -838,7 +842,7 @@ match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) { if (!isa(AddLHS) || cast(AddLHS)->getParent() != BB) { - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -923,7 +927,7 @@ } // If all else fails, see if LVI can figure out a constant value for us. - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -974,7 +978,7 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) { // If the block is trivially dead, just return and let the caller nuke it. // This simplifies other transformations. - if (DDT->pendingDeletedBB(BB) || + if (DTU->isBBPendingDeletion(BB) || (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock())) return false; @@ -991,7 +995,7 @@ LoopHeaders.insert(BB); LVI->eraseBlock(SinglePred); - MergeBasicBlockIntoOnlyPred(BB, nullptr, DDT); + MergeBasicBlockIntoOnlyPred(BB, DTU); // Now that BB is merged into SinglePred (i.e. SinglePred Code followed by // BB code within one basic block `BB`), we need to invalidate the LVI @@ -1088,7 +1092,7 @@ << "' folding undef terminator: " << *BBTerm << '\n'); BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm); BBTerm->eraseFromParent(); - DDT->applyUpdates(Updates); + DTU->applyUpdates(Updates); return true; } @@ -1100,7 +1104,7 @@ << "' folding terminator: " << *BB->getTerminator() << '\n'); ++NumFolds; - ConstantFoldTerminator(BB, true, nullptr, DDT); + ConstantFoldTerminator(BB, true, nullptr, DTU); return true; } @@ -1127,7 +1131,7 @@ // threading is concerned. assert(CondBr->isConditional() && "Threading on unconditional terminator"); - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -1156,7 +1160,7 @@ ConstantInt::getFalse(CondCmp->getType()); ReplaceFoldableUses(CondCmp, CI); } - DDT->deleteEdge(BB, ToRemoveSucc); + DTU->deleteEdgeRelaxed(BB, ToRemoveSucc); return true; } @@ -1240,7 +1244,7 @@ RemoveSucc->removePredecessor(BB); BranchInst::Create(KeepSucc, BI); BI->eraseFromParent(); - DDT->deleteEdge(BB, RemoveSucc); + DTU->deleteEdgeRelaxed(BB, RemoveSucc); return true; } CurrentBB = CurrentPred; @@ -1667,7 +1671,7 @@ TerminatorInst *Term = BB->getTerminator(); BranchInst::Create(OnlyDest, Term); Term->eraseFromParent(); - DDT->applyUpdates(Updates); + DTU->applyUpdates(Updates); // If the condition is now dead due to the removal of the old terminator, // erase it. @@ -1945,7 +1949,7 @@ << "' with cost: " << JumpThreadCost << ", across block:\n " << *BB << "\n"); - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -2009,7 +2013,7 @@ } // Enqueue required DT updates. - DDT->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}, + DTU->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB}, {DominatorTree::Insert, PredBB, NewBB}, {DominatorTree::Delete, PredBB, BB}}); @@ -2105,7 +2109,7 @@ BFI->setBlockFreq(NewBB, NewBBFreq.getFrequency()); } - DDT->applyUpdates(Updates); + DTU->applyUpdates(Updates); return NewBBs[0]; } @@ -2378,7 +2382,7 @@ // Remove the unconditional branch at the end of the PredBB block. OldPredBranch->eraseFromParent(); - DDT->applyUpdates(Updates); + DTU->applyUpdates(Updates); ++NumDupes; return true; @@ -2421,7 +2425,7 @@ // Now check if one of the select values would allow us to constant fold the // terminator in BB. We don't do the transform if both sides fold, those // cases will be threaded in any case. - if (DDT->pending()) + if (DTU->hasPendingDomTreeUpdates()) LVI->disableDT(); else LVI->enableDT(); @@ -2455,7 +2459,7 @@ // The select is now dead. SI->eraseFromParent(); - DDT->applyUpdates({{DominatorTree::Insert, NewBB, BB}, + DTU->applyUpdates({{DominatorTree::Insert, NewBB, BB}, {DominatorTree::Insert, Pred, NewBB}}); // Update any other PHI nodes in BB. for (BasicBlock::iterator BI = BB->begin(); @@ -2548,12 +2552,12 @@ Updates.push_back({DominatorTree::Insert, BB, SplitBB}); Updates.push_back({DominatorTree::Insert, BB, NewBB}); Updates.push_back({DominatorTree::Insert, NewBB, SplitBB}); - // BB's successors were moved to SplitBB, update DDT accordingly. + // BB's successors were moved to SplitBB, update DTU accordingly. for (auto *Succ : successors(SplitBB)) { Updates.push_back({DominatorTree::Delete, BB, Succ}); Updates.push_back({DominatorTree::Insert, SplitBB, Succ}); } - DDT->applyUpdates(Updates); + DTU->applyUpdates(Updates); return true; } return false; @@ -2664,7 +2668,7 @@ // DuplicateInstructionsInSplitBetween inserts a new block "BB.split" between // PredBB and BB. We need to perform two inserts and one delete for each of // the above calls to update Dominators. - DDT->applyUpdates( + DTU->applyUpdates( {// Guarded block split. {DominatorTree::Delete, PredGuardedBlock, BB}, {DominatorTree::Insert, PredGuardedBlock, GuardedBlock}, Index: llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -27,6 +27,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" @@ -41,6 +42,7 @@ static bool simplifyLoopCFG(Loop &L, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE) { bool Changed = false; + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); // Copy blocks into a temporary array to avoid iterator invalidation issues // as we remove them. SmallVector Blocks(L.blocks()); @@ -57,7 +59,7 @@ continue; // Merge Succ into Pred and delete it. - MergeBlockIntoPredecessor(Succ, &DT, &LI); + MergeBlockIntoPredecessor(Succ, &DTU, &LI); SE.forgetLoop(&L); Changed = true; Index: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -28,7 +28,6 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -38,6 +37,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -65,6 +65,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" #include #include @@ -2534,9 +2535,10 @@ // Delete any unreachable statepoints so that we don't have unrewritten // statepoints surviving this pass. This makes testing easier and the // resulting IR less confusing to human readers. - DeferredDominance DD(DT); - bool MadeChange = removeUnreachableBlocks(F, nullptr, &DD); - DD.flush(); + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); + bool MadeChange = removeUnreachableBlocks(F, nullptr, &DTU); + // Flush the Dominator Tree. + DTU.getDomTree(); // Gather all the statepoints which need rewritten. Be careful to only // consider those in reachable code since we need to ask dominance queries Index: llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp +++ llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -20,11 +20,12 @@ #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" -#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Analysis/PostDominators.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -37,6 +38,7 @@ #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Casting.h" +#include "llvm/Transforms/Utils/Local.h" #include #include #include @@ -45,7 +47,7 @@ using namespace llvm; -void llvm::DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT) { +void llvm::DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU) { assert((pred_begin(BB) == pred_end(BB) || // Can delete self loop. BB->getSinglePredecessor() == BB) && "Block is not dead!"); @@ -54,11 +56,11 @@ // Loop through all of our successors and make sure they know that one // of their predecessors is going away. - if (DDT) + if (DTU) Updates.reserve(BBTerm->getNumSuccessors()); for (BasicBlock *Succ : BBTerm->successors()) { Succ->removePredecessor(BB); - if (DDT) + if (DTU) Updates.push_back({DominatorTree::Delete, BB, Succ}); } @@ -74,10 +76,15 @@ I.replaceAllUsesWith(UndefValue::get(I.getType())); BB->getInstList().pop_back(); } - - if (DDT) { - DDT->applyUpdates(Updates); - DDT->deleteBB(BB); // Deferred deletion of BB. + new UnreachableInst(BB->getContext(), BB); + assert(BB->getInstList().size() == 1 && + isa(BB->getTerminator()) && + "The successor list of BB isn't empty before " + "applying corresponding DTU updates."); + + if (DTU) { + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); + DTU->deleteBB(BB); } else { BB->eraseFromParent(); // Zap the block! } @@ -115,11 +122,9 @@ return Changed; } -bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT, +bool llvm::MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU, LoopInfo *LI, - MemoryDependenceResults *MemDep, - DeferredDominance *DDT) { - assert(!(DT && DDT) && "Cannot call with both DT and DDT."); + MemoryDependenceResults *MemDep) { if (BB->hasAddressTaken()) return false; @@ -154,10 +159,10 @@ FoldSingleEntryPHINodes(BB, MemDep); } - // Deferred DT update: Collect all the edges that exit BB. These - // dominator edges will be redirected from Pred. + // DTU update: Collect all the edges that exit BB. + // These dominator edges will be redirected from Pred. std::vector Updates; - if (DDT) { + if (DTU) { Updates.reserve(1 + (2 * succ_size(BB))); Updates.push_back({DominatorTree::Delete, PredBB, BB}); for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { @@ -175,6 +180,7 @@ // Move all definitions in the successor to the predecessor... PredBB->getInstList().splice(PredBB->end(), BB->getInstList()); + new UnreachableInst(BB->getContext(), BB); // Eliminate duplicate dbg.values describing the entry PHI node post-splice. for (auto Incoming : IncomingValues) { @@ -195,28 +201,24 @@ if (!PredBB->hasName()) PredBB->takeName(BB); - // Finally, erase the old block and update dominator info. - if (DT) - if (DomTreeNode *DTN = DT->getNode(BB)) { - DomTreeNode *PredDTN = DT->getNode(PredBB); - SmallVector Children(DTN->begin(), DTN->end()); - for (DomTreeNode *DI : Children) - DT->changeImmediateDominator(DI, PredDTN); - - DT->eraseNode(BB); - } - if (LI) LI->removeBlock(BB); if (MemDep) MemDep->invalidateCachedPredecessors(); - if (DDT) { - DDT->deleteBB(BB); // Deferred deletion of BB. - DDT->applyUpdates(Updates); - } else { - BB->eraseFromParent(); // Nuke BB. + // Finally, erase the old block and update dominator info. + if (DTU) { + assert(BB->getInstList().size() == 1 && + isa(BB->getTerminator()) && + "The successor list of BB isn't empty before " + "applying corresponding DTU updates."); + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); + DTU->deleteBB(BB); + } + + else { + BB->eraseFromParent(); // Nuke BB if DTU is nullptr. } return true; } Index: llvm/trunk/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/Local.cpp +++ llvm/trunk/lib/Transforms/Utils/Local.cpp @@ -47,6 +47,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/GetElementPtrTypeIterator.h" @@ -102,7 +103,7 @@ /// DeleteDeadConditions is true. bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions, const TargetLibraryInfo *TLI, - DeferredDominance *DDT) { + DomTreeUpdater *DTU) { TerminatorInst *T = BB->getTerminator(); IRBuilder<> Builder(T); @@ -125,8 +126,8 @@ // Replace the conditional branch with an unconditional one. Builder.CreateBr(Destination); BI->eraseFromParent(); - if (DDT) - DDT->deleteEdge(BB, OldDest); + if (DTU) + DTU->deleteEdgeRelaxed(BB, OldDest); return true; } @@ -201,8 +202,8 @@ DefaultDest->removePredecessor(ParentBB); i = SI->removeCase(i); e = SI->case_end(); - if (DDT) - DDT->deleteEdge(ParentBB, DefaultDest); + if (DTU) + DTU->deleteEdgeRelaxed(ParentBB, DefaultDest); continue; } @@ -229,7 +230,7 @@ Builder.CreateBr(TheOnlyDest); BasicBlock *BB = SI->getParent(); std::vector Updates; - if (DDT) + if (DTU) Updates.reserve(SI->getNumSuccessors() - 1); // Remove entries from PHI nodes which we no longer branch to... @@ -239,7 +240,7 @@ TheOnlyDest = nullptr; // Don't modify the first branch to TheOnlyDest } else { Succ->removePredecessor(BB); - if (DDT) + if (DTU) Updates.push_back({DominatorTree::Delete, BB, Succ}); } } @@ -249,8 +250,8 @@ SI->eraseFromParent(); if (DeleteDeadConditions) RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI); - if (DDT) - DDT->applyUpdates(Updates); + if (DTU) + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); return true; } @@ -297,7 +298,7 @@ dyn_cast(IBI->getAddress()->stripPointerCasts())) { BasicBlock *TheOnlyDest = BA->getBasicBlock(); std::vector Updates; - if (DDT) + if (DTU) Updates.reserve(IBI->getNumDestinations() - 1); // Insert the new branch. @@ -310,7 +311,7 @@ BasicBlock *ParentBB = IBI->getParent(); BasicBlock *DestBB = IBI->getDestination(i); DestBB->removePredecessor(ParentBB); - if (DDT) + if (DTU) Updates.push_back({DominatorTree::Delete, ParentBB, DestBB}); } } @@ -327,8 +328,8 @@ new UnreachableInst(BB->getContext(), BB); } - if (DDT) - DDT->applyUpdates(Updates); + if (DTU) + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); return true; } } @@ -626,7 +627,7 @@ /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the and to 0. void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - DeferredDominance *DDT) { + DomTreeUpdater *DTU) { // This only adjusts blocks with PHI nodes. if (!isa(BB->begin())) return; @@ -649,17 +650,16 @@ // of the block. if (PhiIt != OldPhiIt) PhiIt = &BB->front(); } - if (DDT) - DDT->deleteEdge(Pred, BB); + if (DTU) + DTU->deleteEdgeRelaxed(Pred, BB); } /// MergeBasicBlockIntoOnlyPred - DestBB is a block with one predecessor and its /// predecessor is known to have one successor (DestBB!). Eliminate the edge /// between them, moving the instructions in the predecessor into DestBB and /// deleting the predecessor block. -void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB, DominatorTree *DT, - DeferredDominance *DDT) { - assert(!(DT && DDT) && "Cannot call with both DT and DDT."); +void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB, + DomTreeUpdater *DTU) { // If BB has single-entry PHI nodes, fold them. while (PHINode *PN = dyn_cast(DestBB->begin())) { @@ -677,10 +677,11 @@ if (PredBB == &DestBB->getParent()->getEntryBlock()) ReplaceEntryBB = true; - // Deferred DT update: Collect all the edges that enter PredBB. These - // dominator edges will be redirected to DestBB. + // DTU updates: Collect all the edges that enter + // PredBB. These dominator edges will be redirected to DestBB. std::vector Updates; - if (DDT && !ReplaceEntryBB) { + + if (DTU) { Updates.reserve(1 + (2 * pred_size(PredBB))); Updates.push_back({DominatorTree::Delete, PredBB, DestBB}); for (auto I = pred_begin(PredBB), E = pred_end(PredBB); I != E; ++I) { @@ -708,33 +709,32 @@ // Splice all the instructions from PredBB to DestBB. PredBB->getTerminator()->eraseFromParent(); DestBB->getInstList().splice(DestBB->begin(), PredBB->getInstList()); + new UnreachableInst(PredBB->getContext(), PredBB); // If the PredBB is the entry block of the function, move DestBB up to // become the entry block after we erase PredBB. if (ReplaceEntryBB) DestBB->moveAfter(PredBB); - if (DT) { - // For some irreducible CFG we end up having forward-unreachable blocks - // so check if getNode returns a valid node before updating the domtree. - if (DomTreeNode *DTN = DT->getNode(PredBB)) { - BasicBlock *PredBBIDom = DTN->getIDom()->getBlock(); - DT->changeImmediateDominator(DestBB, PredBBIDom); - DT->eraseNode(PredBB); + if (DTU) { + assert(PredBB->getInstList().size() == 1 && + isa(PredBB->getTerminator()) && + "The successor list of PredBB isn't empty before " + "applying corresponding DTU updates."); + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); + DTU->deleteBB(PredBB); + // Recalculation of DomTree is needed when updating a forward DomTree and + // the Entry BB is replaced. + if (ReplaceEntryBB && DTU->hasDomTree()) { + // The entry block was removed and there is no external interface for + // the dominator tree to be notified of this change. In this corner-case + // we recalculate the entire tree. + DTU->recalculate(*(DestBB->getParent())); } } - if (DDT) { - DDT->deleteBB(PredBB); // Deferred deletion of BB. - if (ReplaceEntryBB) - // The entry block was removed and there is no external interface for the - // dominator tree to be notified of this change. In this corner-case we - // recalculate the entire tree. - DDT->recalculate(*(DestBB->getParent())); - else - DDT->applyUpdates(Updates); - } else { - PredBB->eraseFromParent(); // Nuke BB. + else { + PredBB->eraseFromParent(); // Nuke BB if DTU is nullptr. } } @@ -945,7 +945,7 @@ /// eliminate BB by rewriting all the predecessors to branch to the successor /// block and return true. If we can't transform, return false. bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB, - DeferredDominance *DDT) { + DomTreeUpdater *DTU) { assert(BB != &BB->getParent()->getEntryBlock() && "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!"); @@ -987,7 +987,7 @@ LLVM_DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB); std::vector Updates; - if (DDT) { + if (DTU) { Updates.reserve(1 + (2 * pred_size(BB))); Updates.push_back({DominatorTree::Delete, BB, Succ}); // All predecessors of BB will be moved to Succ. @@ -1044,9 +1044,16 @@ BB->replaceAllUsesWith(Succ); if (!Succ->hasName()) Succ->takeName(BB); - if (DDT) { - DDT->deleteBB(BB); // Deferred deletion of the old basic block. - DDT->applyUpdates(Updates); + // Clear the successor list of BB to match updates applying to DTU later. + if (BB->getTerminator()) + BB->getInstList().pop_back(); + new UnreachableInst(BB->getContext(), BB); + assert(succ_empty(BB) && "The successor list of BB isn't empty before " + "applying corresponding DTU updates."); + + if (DTU) { + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); + DTU->deleteBB(BB); } else { BB->eraseFromParent(); // Delete the old basic block. } @@ -1902,17 +1909,17 @@ } unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap, - bool PreserveLCSSA, DeferredDominance *DDT) { + bool PreserveLCSSA, DomTreeUpdater *DTU) { BasicBlock *BB = I->getParent(); std::vector Updates; // Loop over all of the successors, removing BB's entry from any PHI // nodes. - if (DDT) + if (DTU) Updates.reserve(BB->getTerminator()->getNumSuccessors()); for (BasicBlock *Successor : successors(BB)) { Successor->removePredecessor(BB, PreserveLCSSA); - if (DDT) + if (DTU) Updates.push_back({DominatorTree::Delete, BB, Successor}); } // Insert a call to llvm.trap right before this. This turns the undefined @@ -1934,13 +1941,13 @@ BB->getInstList().erase(BBI++); ++NumInstrsRemoved; } - if (DDT) - DDT->applyUpdates(Updates); + if (DTU) + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); return NumInstrsRemoved; } /// changeToCall - Convert the specified invoke into a normal call. -static void changeToCall(InvokeInst *II, DeferredDominance *DDT = nullptr) { +static void changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr) { SmallVector Args(II->arg_begin(), II->arg_end()); SmallVector OpBundles; II->getOperandBundlesAsDefs(OpBundles); @@ -1961,8 +1968,8 @@ BasicBlock *UnwindDestBB = II->getUnwindDest(); UnwindDestBB->removePredecessor(BB); II->eraseFromParent(); - if (DDT) - DDT->deleteEdge(BB, UnwindDestBB); + if (DTU) + DTU->deleteEdgeRelaxed(BB, UnwindDestBB); } BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI, @@ -2003,8 +2010,8 @@ } static bool markAliveBlocks(Function &F, - SmallPtrSetImpl &Reachable, - DeferredDominance *DDT = nullptr) { + SmallPtrSetImpl &Reachable, + DomTreeUpdater *DTU = nullptr) { SmallVector Worklist; BasicBlock *BB = &F.front(); Worklist.push_back(BB); @@ -2029,7 +2036,7 @@ if (IntrinsicID == Intrinsic::assume) { if (match(CI->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) { // Don't insert a call to llvm.trap right before the unreachable. - changeToUnreachable(CI, false, false, DDT); + changeToUnreachable(CI, false, false, DTU); Changed = true; break; } @@ -2046,7 +2053,7 @@ if (match(CI->getArgOperand(0), m_Zero())) if (!isa(CI->getNextNode())) { changeToUnreachable(CI->getNextNode(), /*UseLLVMTrap=*/false, - false, DDT); + false, DTU); Changed = true; break; } @@ -2054,7 +2061,7 @@ } else if ((isa(Callee) && !NullPointerIsDefined(CI->getFunction())) || isa(Callee)) { - changeToUnreachable(CI, /*UseLLVMTrap=*/false, false, DDT); + changeToUnreachable(CI, /*UseLLVMTrap=*/false, false, DTU); Changed = true; break; } @@ -2064,7 +2071,7 @@ // though. if (!isa(CI->getNextNode())) { // Don't insert a call to llvm.trap right before the unreachable. - changeToUnreachable(CI->getNextNode(), false, false, DDT); + changeToUnreachable(CI->getNextNode(), false, false, DTU); Changed = true; } break; @@ -2083,7 +2090,7 @@ (isa(Ptr) && !NullPointerIsDefined(SI->getFunction(), SI->getPointerAddressSpace()))) { - changeToUnreachable(SI, true, false, DDT); + changeToUnreachable(SI, true, false, DTU); Changed = true; break; } @@ -2097,7 +2104,7 @@ if ((isa(Callee) && !NullPointerIsDefined(BB->getParent())) || isa(Callee)) { - changeToUnreachable(II, true, false, DDT); + changeToUnreachable(II, true, false, DTU); Changed = true; } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) { if (II->use_empty() && II->onlyReadsMemory()) { @@ -2107,10 +2114,10 @@ BranchInst::Create(NormalDestBB, II); UnwindDestBB->removePredecessor(II->getParent()); II->eraseFromParent(); - if (DDT) - DDT->deleteEdge(BB, UnwindDestBB); + if (DTU) + DTU->deleteEdgeRelaxed(BB, UnwindDestBB); } else - changeToCall(II, DDT); + changeToCall(II, DTU); Changed = true; } } else if (auto *CatchSwitch = dyn_cast(Terminator)) { @@ -2156,7 +2163,7 @@ } } - Changed |= ConstantFoldTerminator(BB, true, nullptr, DDT); + Changed |= ConstantFoldTerminator(BB, true, nullptr, DTU); for (BasicBlock *Successor : successors(BB)) if (Reachable.insert(Successor).second) Worklist.push_back(Successor); @@ -2164,11 +2171,11 @@ return Changed; } -void llvm::removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT) { +void llvm::removeUnwindEdge(BasicBlock *BB, DomTreeUpdater *DTU) { TerminatorInst *TI = BB->getTerminator(); if (auto *II = dyn_cast(TI)) { - changeToCall(II, DDT); + changeToCall(II, DTU); return; } @@ -2196,8 +2203,8 @@ UnwindDest->removePredecessor(BB); TI->replaceAllUsesWith(NewTI); TI->eraseFromParent(); - if (DDT) - DDT->deleteEdge(BB, UnwindDest); + if (DTU) + DTU->deleteEdgeRelaxed(BB, UnwindDest); } /// removeUnreachableBlocks - Remove blocks that are not reachable, even @@ -2205,9 +2212,9 @@ /// otherwise. If `LVI` is passed, this function preserves LazyValueInfo /// after modifying the CFG. bool llvm::removeUnreachableBlocks(Function &F, LazyValueInfo *LVI, - DeferredDominance *DDT) { + DomTreeUpdater *DTU) { SmallPtrSet Reachable; - bool Changed = markAliveBlocks(F, Reachable, DDT); + bool Changed = markAliveBlocks(F, Reachable, DTU); // If there are unreachable blocks in the CFG... if (Reachable.size() == F.size()) @@ -2217,7 +2224,7 @@ NumRemoved += F.size()-Reachable.size(); // Loop over all of the basic blocks that are not reachable, dropping all of - // their internal references. Update DDT and LVI if available. + // their internal references. Update DTU and LVI if available. std::vector Updates; for (Function::iterator I = ++F.begin(), E = F.end(); I != E; ++I) { auto *BB = &*I; @@ -2226,30 +2233,40 @@ for (BasicBlock *Successor : successors(BB)) { if (Reachable.count(Successor)) Successor->removePredecessor(BB); - if (DDT) + if (DTU) Updates.push_back({DominatorTree::Delete, BB, Successor}); } if (LVI) LVI->eraseBlock(BB); BB->dropAllReferences(); } - + SmallVector ToDeleteBBs; for (Function::iterator I = ++F.begin(); I != F.end();) { auto *BB = &*I; if (Reachable.count(BB)) { ++I; continue; } - if (DDT) { - DDT->deleteBB(BB); // deferred deletion of BB. + if (DTU) { + ToDeleteBBs.push_back(BB); + + // Remove the TerminatorInst of BB to clear the successor list of BB. + if (BB->getTerminator()) + BB->getInstList().pop_back(); + new UnreachableInst(BB->getContext(), BB); + assert(succ_empty(BB) && "The successor list of BB isn't empty before " + "applying corresponding DTU updates."); ++I; } else { I = F.getBasicBlockList().erase(I); } } - if (DDT) - DDT->applyUpdates(Updates); + if (DTU) { + DTU->applyUpdates(Updates, /*ForceRemoveDuplicates*/ true); + for (auto *BB : ToDeleteBBs) + DTU->deleteBB(BB); + } return true; } Index: llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp +++ llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -23,10 +23,10 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/CFG.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IntrinsicInst.h" @@ -35,6 +35,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -476,7 +477,8 @@ // the OrigHeader block into OrigLatch. This will succeed if they are // connected by an unconditional branch. This is just a cleanup so the // emitted code isn't too gross in this common case. - MergeBlockIntoPredecessor(OrigHeader, DT, LI); + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); + MergeBlockIntoPredecessor(OrigHeader, &DTU, LI); LLVM_DEBUG(dbgs() << "LoopRotation: into "; L->dump()); Index: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp +++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" @@ -1425,12 +1426,13 @@ // Remove the old branch. Preheader->getTerminator()->eraseFromParent(); + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); if (DT) { // Update the dominator tree by informing it about the new edge from the // preheader to the exit. - DT->insertEdge(Preheader, ExitBlock); + DTU.insertEdge(Preheader, ExitBlock); // Inform the dominator tree about the removed edge. - DT->deleteEdge(Preheader, L->getHeader()); + DTU.deleteEdge(Preheader, L->getHeader()); } // Given LCSSA form is satisfied, we should not have users of instructions Index: llvm/trunk/unittests/Transforms/Utils/Local.cpp =================================================================== --- llvm/trunk/unittests/Transforms/Utils/Local.cpp +++ llvm/trunk/unittests/Transforms/Utils/Local.cpp @@ -8,9 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/Local.h" +#include "llvm/Analysis/PostDominators.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -176,9 +178,10 @@ TEST(Local, MergeBasicBlockIntoOnlyPred) { LLVMContext C; - - std::unique_ptr M = parseIR(C, - R"( + std::unique_ptr M; + auto resetIR = [&]() { + M = parseIR(C, + R"( define i32 @f(i8* %str) { entry: br label %bb2.i @@ -195,18 +198,137 @@ ret i32 0 } )"); - runWithDomTree( - *M, "f", [&](Function &F, DominatorTree *DT) { - for (Function::iterator I = F.begin(), E = F.end(); I != E;) { - BasicBlock *BB = &*I++; - BasicBlock *SinglePred = BB->getSinglePredecessor(); - if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue; - BranchInst *Term = dyn_cast(SinglePred->getTerminator()); - if (Term && !Term->isConditional()) - MergeBasicBlockIntoOnlyPred(BB, DT); - } - EXPECT_TRUE(DT->verify()); - }); + }; + + auto resetIRReplaceEntry = [&]() { + M = parseIR(C, + R"( + define i32 @f() { + entry: + br label %bb2.i + bb2.i: ; preds = %entry + ret i32 0 + } + )"); + }; + + auto Test = [&](Function &F, DomTreeUpdater &DTU) { + for (Function::iterator I = F.begin(), E = F.end(); I != E;) { + BasicBlock *BB = &*I++; + BasicBlock *SinglePred = BB->getSinglePredecessor(); + if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) + continue; + BranchInst *Term = dyn_cast(SinglePred->getTerminator()); + if (Term && !Term->isConditional()) + MergeBasicBlockIntoOnlyPred(BB, &DTU); + } + if (DTU.hasDomTree()) + EXPECT_TRUE(DTU.getDomTree().verify()); + if (DTU.hasPostDomTree()) + EXPECT_TRUE(DTU.getPostDomTree().verify()); + }; + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // both DT and PDT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // DT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // PDT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with + // both DT and PDT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with + // PDT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with DT. + resetIR(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // both DT and PDT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // DT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Eager UpdateStrategy with + // PDT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Eager); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with + // both DT and PDT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with + // PDT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(PDT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); + + // Test MergeBasicBlockIntoOnlyPred working under Lazy UpdateStrategy with DT. + resetIRReplaceEntry(); + runWithDomTree(*M, "f", [&](Function &F, DominatorTree *DT) { + DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy); + Test(F, DTU); + }); } TEST(Local, ConstantFoldTerminator) { @@ -310,27 +432,55 @@ } )"); - auto CFAllTerminators = [&](Function &F, DominatorTree *DT) { - DeferredDominance DDT(*DT); + auto CFAllTerminatorsEager = [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager); for (Function::iterator I = F.begin(), E = F.end(); I != E;) { BasicBlock *BB = &*I++; - ConstantFoldTerminator(BB, true, nullptr, &DDT); + ConstantFoldTerminator(BB, true, nullptr, &DTU); } - EXPECT_TRUE(DDT.flush().verify()); + EXPECT_TRUE(DTU.getDomTree().verify()); + EXPECT_TRUE(DTU.getPostDomTree().verify()); }; - runWithDomTree(*M, "br_same_dest", CFAllTerminators); - runWithDomTree(*M, "br_different_dest", CFAllTerminators); - runWithDomTree(*M, "switch_2_different_dest", CFAllTerminators); - runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminators); - runWithDomTree(*M, "switch_3_different_dest", CFAllTerminators); - runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminators); - runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminators); - runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminators); - runWithDomTree(*M, "indirectbr", CFAllTerminators); - runWithDomTree(*M, "indirectbr_repeated", CFAllTerminators); - runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminators); + auto CFAllTerminatorsLazy = [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy); + for (Function::iterator I = F.begin(), E = F.end(); I != E;) { + BasicBlock *BB = &*I++; + ConstantFoldTerminator(BB, true, nullptr, &DTU); + } + + EXPECT_TRUE(DTU.getDomTree().verify()); + EXPECT_TRUE(DTU.getPostDomTree().verify()); + }; + + // Test ConstantFoldTerminator under Eager UpdateStrategy. + runWithDomTree(*M, "br_same_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "br_different_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_2_different_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_3_different_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminatorsEager); + runWithDomTree(*M, "indirectbr", CFAllTerminatorsEager); + runWithDomTree(*M, "indirectbr_repeated", CFAllTerminatorsEager); + runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminatorsEager); + + // Test ConstantFoldTerminator under Lazy UpdateStrategy. + runWithDomTree(*M, "br_same_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "br_different_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_2_different_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_3_different_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminatorsLazy); + runWithDomTree(*M, "indirectbr", CFAllTerminatorsLazy); + runWithDomTree(*M, "indirectbr_repeated", CFAllTerminatorsLazy); + runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminatorsLazy); } struct SalvageDebugInfoTest : ::testing::Test { @@ -618,3 +768,80 @@ verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo); } + +TEST(Local, RemoveUnreachableBlocks) { + LLVMContext C; + + std::unique_ptr M = parseIR(C, + R"( + define void @br_simple() { + entry: + br label %bb0 + bb0: + ret void + bb1: + ret void + } + + define void @br_self_loop() { + entry: + br label %bb0 + bb0: + br i1 true, label %bb1, label %bb0 + bb1: + br i1 true, label %bb0, label %bb2 + bb2: + br label %bb2 + } + + define void @br_constant() { + entry: + br label %bb0 + bb0: + br i1 true, label %bb1, label %bb2 + bb1: + br i1 true, label %bb0, label %bb2 + bb2: + br label %bb2 + } + + define void @br_loop() { + entry: + br label %bb0 + bb0: + br label %bb0 + bb1: + br label %bb2 + bb2: + br label %bb1 + } + )"); + + auto runEager = [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Eager); + removeUnreachableBlocks(F, nullptr, &DTU); + EXPECT_TRUE(DTU.getDomTree().verify()); + EXPECT_TRUE(DTU.getPostDomTree().verify()); + }; + + auto runLazy = [&](Function &F, DominatorTree *DT) { + PostDominatorTree PDT = PostDominatorTree(F); + DomTreeUpdater DTU(*DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy); + removeUnreachableBlocks(F, nullptr, &DTU); + EXPECT_TRUE(DTU.getDomTree().verify()); + EXPECT_TRUE(DTU.getPostDomTree().verify()); + }; + + // Test removeUnreachableBlocks under Eager UpdateStrategy. + runWithDomTree(*M, "br_simple", runEager); + runWithDomTree(*M, "br_self_loop", runEager); + runWithDomTree(*M, "br_constant", runEager); + runWithDomTree(*M, "br_loop", runEager); + + // Test removeUnreachableBlocks under Lazy UpdateStrategy. + runWithDomTree(*M, "br_simple", runLazy); + runWithDomTree(*M, "br_self_loop", runLazy); + runWithDomTree(*M, "br_constant", runLazy); + runWithDomTree(*M, "br_loop", runLazy); +} \ No newline at end of file