[llvm] r314435 - [JumpThreading] Preserve DT and LVI across the pass

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 29 08:29:11 PDT 2017


Er, have you checked the history here?  I thought this preservation was 
removed relatively recently to avoid a correctness bug.

Philip


On 09/28/2017 10:24 AM, Evandro Menezes via llvm-commits wrote:
> Author: evandro
> Date: Thu Sep 28 10:24:40 2017
> New Revision: 314435
>
> URL: http://llvm.org/viewvc/llvm-project?rev=314435&view=rev
> Log:
> [JumpThreading] Preserve DT and LVI across the pass
>
> JumpThreading now preserves dominance and lazy value information across the
> entire pass.  The pass manager is also informed of this preservation with
> the goal of DT and LVI being recalculated fewer times overall during
> compilation.
>
> This change prepares JumpThreading for enhanced opportunities; particularly
> those across loop boundaries.
>
> Patch by: Brian Rzycki <b.rzycki at samsung.com>,
>            Sebastian Pop <s.pop at samsung.com>
>
> Differential revision: https://reviews.llvm.org/D37528
>
> Modified:
>      llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h
>      llvm/trunk/include/llvm/Transforms/Utils/Local.h
>      llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
>      llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
>      llvm/trunk/lib/Transforms/Utils/Local.cpp
>      llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll
>
> Modified: llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h Thu Sep 28 10:24:40 2017
> @@ -34,6 +34,7 @@ class BinaryOperator;
>   class BranchInst;
>   class CmpInst;
>   class Constant;
> +class DominatorTree;
>   class Function;
>   class Instruction;
>   class IntrinsicInst;
> @@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInf
>     TargetLibraryInfo *TLI;
>     LazyValueInfo *LVI;
>     AliasAnalysis *AA;
> +  DominatorTree *DT;
>     std::unique_ptr<BlockFrequencyInfo> BFI;
>     std::unique_ptr<BranchProbabilityInfo> BPI;
>     bool HasProfileData = false;
> @@ -107,7 +109,7 @@ public:
>   
>     // Glue for old PM.
>     bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
> -               AliasAnalysis *AA_, bool HasProfileData_,
> +               AliasAnalysis *AA_, DominatorTree *DT_, bool HasProfileData_,
>                  std::unique_ptr<BlockFrequencyInfo> BFI_,
>                  std::unique_ptr<BranchProbabilityInfo> BPI_);
>   
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Thu Sep 28 10:24:40 2017
> @@ -79,7 +79,8 @@ struct SimplifyCFGOptions {
>   /// conditions and indirectbr addresses this might make dead if
>   /// DeleteDeadConditions is true.
>   bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
> -                            const TargetLibraryInfo *TLI = nullptr);
> +                            const TargetLibraryInfo *TLI = nullptr,
> +                            DominatorTree *DT = nullptr);
>   
>   //===----------------------------------------------------------------------===//
>   //  Local dead code elimination.
> @@ -133,7 +134,8 @@ bool SimplifyInstructionsInBlock(BasicBl
>   ///
>   /// .. and delete the predecessor corresponding to the '1', this will attempt to
>   /// recursively fold the 'and' to 0.
> -void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred);
> +void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
> +                                  DominatorTree *DT = 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
> @@ -144,7 +146,8 @@ void MergeBasicBlockIntoOnlyPred(BasicBl
>   /// 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);
> +bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
> +                                             DominatorTree *DT = 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
> @@ -342,7 +345,8 @@ unsigned removeAllNonTerminatorAndEHPadI
>   /// Insert an unreachable instruction before the specified
>   /// instruction, making it and the rest of the code in the block dead.
>   unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap,
> -                             bool PreserveLCSSA = false);
> +                             bool PreserveLCSSA = false,
> +                             DominatorTree *DT = nullptr);
>   
>   /// Convert the CallInst to InvokeInst with the specified unwind edge basic
>   /// block.  This also splits the basic block where CI is located, because
> @@ -357,12 +361,13 @@ BasicBlock *changeToInvokeAndSplitBasicB
>   ///
>   /// \param BB  Block whose terminator will be replaced.  Its terminator must
>   ///            have an unwind successor.
> -void removeUnwindEdge(BasicBlock *BB);
> +void removeUnwindEdge(BasicBlock *BB, DominatorTree *DT = 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);
> +bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr,
> +                             DominatorTree *DT = nullptr);
>   
>   /// Combine the metadata of two instructions so that K can replace J
>   ///
>
> Modified: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp Thu Sep 28 10:24:40 2017
> @@ -55,6 +55,7 @@ namespace {
>       bool runOnFunction(Function &F) override;
>   
>       void getAnalysisUsage(AnalysisUsage &AU) const override {
> +      AU.addRequired<DominatorTreeWrapperPass>();
>         AU.addRequired<LazyValueInfoWrapperPass>();
>         AU.addPreserved<GlobalsAAWrapperPass>();
>       }
> @@ -64,6 +65,7 @@ namespace {
>   char CorrelatedValuePropagation::ID = 0;
>   INITIALIZE_PASS_BEGIN(CorrelatedValuePropagation, "correlated-propagation",
>                   "Value Propagation", false, false)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>   INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
>   INITIALIZE_PASS_END(CorrelatedValuePropagation, "correlated-propagation",
>                   "Value Propagation", false, false)
>
> Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Thu Sep 28 10:24:40 2017
> @@ -131,10 +131,11 @@ namespace {
>       bool runOnFunction(Function &F) override;
>   
>       void getAnalysisUsage(AnalysisUsage &AU) const override {
> -      if (PrintLVIAfterJumpThreading)
> -        AU.addRequired<DominatorTreeWrapperPass>();
> +      AU.addRequired<DominatorTreeWrapperPass>();
> +      AU.addPreserved<DominatorTreeWrapperPass>();
>         AU.addRequired<AAResultsWrapperPass>();
>         AU.addRequired<LazyValueInfoWrapperPass>();
> +      AU.addPreserved<LazyValueInfoWrapperPass>();
>         AU.addPreserved<GlobalsAAWrapperPass>();
>         AU.addRequired<TargetLibraryInfoWrapperPass>();
>       }
> @@ -148,6 +149,7 @@ char JumpThreading::ID = 0;
>   
>   INITIALIZE_PASS_BEGIN(JumpThreading, "jump-threading",
>                   "Jump Threading", false, false)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>   INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
>   INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
>   INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
> @@ -277,6 +279,9 @@ bool JumpThreading::runOnFunction(Functi
>     if (skipFunction(F))
>       return false;
>     auto TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
> +  // Get DT analysis before LVI. When LVI is initialized it conditionally adds
> +  // DT if it's available.
> +  auto DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>     auto LVI = &getAnalysis<LazyValueInfoWrapperPass>().getLVI();
>     auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
>     std::unique_ptr<BlockFrequencyInfo> BFI;
> @@ -288,12 +293,11 @@ bool JumpThreading::runOnFunction(Functi
>       BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));
>     }
>   
> -  bool Changed = Impl.runImpl(F, TLI, LVI, AA, HasProfileData, std::move(BFI),
> -                              std::move(BPI));
> +  bool Changed = Impl.runImpl(F, TLI, LVI, AA, DT, HasProfileData,
> +                              std::move(BFI), std::move(BPI));
>     if (PrintLVIAfterJumpThreading) {
>       dbgs() << "LVI for function '" << F.getName() << "':\n";
> -    LVI->printLVI(F, getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
> -                  dbgs());
> +    LVI->printLVI(F, *DT, dbgs());
>     }
>     return Changed;
>   }
> @@ -301,6 +305,9 @@ bool JumpThreading::runOnFunction(Functi
>   PreservedAnalyses JumpThreadingPass::run(Function &F,
>                                            FunctionAnalysisManager &AM) {
>     auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
> +  // Get DT analysis before LVI. When LVI is initialized it conditionally adds
> +  // DT if it's available.
> +  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
>     auto &LVI = AM.getResult<LazyValueAnalysis>(F);
>     auto &AA = AM.getResult<AAManager>(F);
>   
> @@ -313,25 +320,28 @@ PreservedAnalyses JumpThreadingPass::run
>       BFI.reset(new BlockFrequencyInfo(F, *BPI, LI));
>     }
>   
> -  bool Changed = runImpl(F, &TLI, &LVI, &AA, HasProfileData, std::move(BFI),
> -                         std::move(BPI));
> +  bool Changed = runImpl(F, &TLI, &LVI, &AA, &DT, HasProfileData,
> +                         std::move(BFI), std::move(BPI));
>   
>     if (!Changed)
>       return PreservedAnalyses::all();
>     PreservedAnalyses PA;
>     PA.preserve<GlobalsAA>();
> +  PA.preserve<DominatorTreeAnalysis>();
> +  PA.preserve<LazyValueAnalysis>();
>     return PA;
>   }
>   
>   bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
>                                   LazyValueInfo *LVI_, AliasAnalysis *AA_,
> -                                bool HasProfileData_,
> +                                DominatorTree *DT_, bool HasProfileData_,
>                                   std::unique_ptr<BlockFrequencyInfo> BFI_,
>                                   std::unique_ptr<BranchProbabilityInfo> BPI_) {
>     DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n");
>     TLI = TLI_;
>     LVI = LVI_;
>     AA = AA_;
> +  DT = DT_;
>     BFI.reset();
>     BPI.reset();
>     // When profile data is available, we need to update edge weights after
> @@ -353,8 +363,7 @@ bool JumpThreadingPass::runImpl(Function
>     // back edges. This works for normal cases but not for unreachable blocks as
>     // they may have cycle with no back edge.
>     bool EverChanged = false;
> -  EverChanged |= removeUnreachableBlocks(F, LVI);
> -
> +  EverChanged |= removeUnreachableBlocks(F, LVI, DT);
>     FindLoopHeaders(F);
>   
>     bool Changed;
> @@ -400,7 +409,7 @@ bool JumpThreadingPass::runImpl(Function
>           // awesome, but it allows us to use AssertingVH to prevent nasty
>           // dangling pointer issues within LazyValueInfo.
>           LVI->eraseBlock(BB);
> -        if (TryToSimplifyUncondBranchFromEmptyBlock(BB))
> +        if (TryToSimplifyUncondBranchFromEmptyBlock(BB, DT))
>             Changed = true;
>         }
>       }
> @@ -948,7 +957,7 @@ bool JumpThreadingPass::ProcessBlock(Bas
>           LoopHeaders.insert(BB);
>   
>         LVI->eraseBlock(SinglePred);
> -      MergeBasicBlockIntoOnlyPred(BB);
> +      MergeBasicBlockIntoOnlyPred(BB, DT);
>   
>         // 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
> @@ -1031,18 +1040,27 @@ bool JumpThreadingPass::ProcessBlock(Bas
>     // successors to branch to.  Let GetBestDestForJumpOnUndef decide.
>     if (isa<UndefValue>(Condition)) {
>       unsigned BestSucc = GetBestDestForJumpOnUndef(BB);
> +    std::vector<DominatorTree::UpdateType> Updates;
>   
>       // Fold the branch/switch.
>       TerminatorInst *BBTerm = BB->getTerminator();
>       for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) {
>         if (i == BestSucc) continue;
> -      BBTerm->getSuccessor(i)->removePredecessor(BB, true);
> +      BasicBlock *Succ = BBTerm->getSuccessor(i);
> +      Succ->removePredecessor(BB, true);
> +      if (Succ == BB)
> +        continue;
> +      DominatorTree::UpdateType UT = {DominatorTree::Delete, BB, Succ};
> +      // Make sure to remove a DT edge exactly once and not an edge to itself.
> +      if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +        Updates.push_back(UT);
>       }
>   
>       DEBUG(dbgs() << "  In block '" << BB->getName()
>             << "' folding undef terminator: " << *BBTerm << '\n');
>       BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm);
>       BBTerm->eraseFromParent();
> +    DT->applyUpdates(Updates);
>       return true;
>     }
>   
> @@ -1053,7 +1071,7 @@ bool JumpThreadingPass::ProcessBlock(Bas
>       DEBUG(dbgs() << "  In block '" << BB->getName()
>             << "' folding terminator: " << *BB->getTerminator() << '\n');
>       ++NumFolds;
> -    ConstantFoldTerminator(BB, true);
> +    ConstantFoldTerminator(BB, true, nullptr, DT);
>       return true;
>     }
>   
> @@ -1086,9 +1104,12 @@ bool JumpThreadingPass::ProcessBlock(Bas
>         if (Ret != LazyValueInfo::Unknown) {
>           unsigned ToRemove = Ret == LazyValueInfo::True ? 1 : 0;
>           unsigned ToKeep = Ret == LazyValueInfo::True ? 0 : 1;
> -        CondBr->getSuccessor(ToRemove)->removePredecessor(BB, true);
> +        BasicBlock *ToRemoveSucc = CondBr->getSuccessor(ToRemove);
> +        ToRemoveSucc->removePredecessor(BB, true);
>           BranchInst::Create(CondBr->getSuccessor(ToKeep), CondBr);
>           CondBr->eraseFromParent();
> +        if (BB != ToRemoveSucc)
> +          DT->deleteEdge(BB, ToRemoveSucc);
>           if (CondCmp->use_empty())
>             CondCmp->eraseFromParent();
>           // We can safely replace *some* uses of the CondInst if it has
> @@ -1182,9 +1203,12 @@ bool JumpThreadingPass::ProcessImpliedCo
>       Optional<bool> Implication =
>           isImpliedCondition(PBI->getCondition(), Cond, DL, CondIsTrue);
>       if (Implication) {
> -      BI->getSuccessor(*Implication ? 1 : 0)->removePredecessor(BB);
> +      BasicBlock *RemoveSucc = BI->getSuccessor(*Implication ? 1 : 0);
> +      RemoveSucc->removePredecessor(BB);
>         BranchInst::Create(BI->getSuccessor(*Implication ? 0 : 1), BI);
>         BI->eraseFromParent();
> +      if (BB != RemoveSucc)
> +        DT->deleteEdge(BB, RemoveSucc);
>         return true;
>       }
>       CurrentBB = CurrentPred;
> @@ -1576,18 +1600,27 @@ bool JumpThreadingPass::ProcessThreadabl
>     if (OnlyDest && OnlyDest != MultipleDestSentinel) {
>       if (PredWithKnownDest ==
>           (size_t)std::distance(pred_begin(BB), pred_end(BB))) {
> +      std::vector<DominatorTree::UpdateType> Updates;
>         bool SeenFirstBranchToOnlyDest = false;
>         for (BasicBlock *SuccBB : successors(BB)) {
> -        if (SuccBB == OnlyDest && !SeenFirstBranchToOnlyDest)
> +        if (SuccBB == OnlyDest && !SeenFirstBranchToOnlyDest) {
>             SeenFirstBranchToOnlyDest = true; // Don't modify the first branch.
> -        else
> +        } else {
>             SuccBB->removePredecessor(BB, true); // This is unreachable successor.
> +          if (SuccBB != OnlyDest && SuccBB != BB) {
> +            DominatorTree::UpdateType UT = {DominatorTree::Delete, BB, SuccBB};
> +            // Make sure to remove a DT edge exactly once.
> +            if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +              Updates.push_back(UT);
> +          }
> +        }
>         }
>   
>         // Finally update the terminator.
>         TerminatorInst *Term = BB->getTerminator();
>         BranchInst::Create(OnlyDest, Term);
>         Term->eraseFromParent();
> +      DT->applyUpdates(Updates);
>   
>         // If the condition is now dead due to the removal of the old terminator,
>         // erase it.
> @@ -1922,7 +1955,6 @@ bool JumpThreadingPass::ThreadEdge(Basic
>   
>         UsesToRename.push_back(&U);
>       }
> -
>       // If there are no uses outside the block, we're done with this instruction.
>       if (UsesToRename.empty())
>         continue;
> @@ -1951,6 +1983,10 @@ bool JumpThreadingPass::ThreadEdge(Basic
>         PredTerm->setSuccessor(i, NewBB);
>       }
>   
> +  DT->applyUpdates({{DominatorTree::Insert, NewBB, SuccBB},
> +                    {DominatorTree::Insert, PredBB, NewBB},
> +                    {DominatorTree::Delete, PredBB, BB}});
> +
>     // At this point, the IR is fully up to date and consistent.  Do a quick scan
>     // over the new instructions and zap any that are constants or dead.  This
>     // frequently happens because of phi translation.
> @@ -1977,7 +2013,7 @@ BasicBlock *JumpThreadingPass::SplitBloc
>       for (auto Pred : Preds)
>         PredBBFreq += BFI->getBlockFreq(Pred) * BPI->getEdgeProbability(Pred, BB);
>   
> -  BasicBlock *PredBB = SplitBlockPredecessors(BB, Preds, Suffix);
> +  BasicBlock *PredBB = SplitBlockPredecessors(BB, Preds, Suffix, DT);
>   
>     // Set the block frequency of the newly created PredBB, which is the sum of
>     // frequencies of Preds.
> @@ -2147,7 +2183,7 @@ bool JumpThreadingPass::DuplicateCondBra
>     BranchInst *OldPredBranch = dyn_cast<BranchInst>(PredBB->getTerminator());
>   
>     if (!OldPredBranch || !OldPredBranch->isUnconditional()) {
> -    PredBB = SplitEdge(PredBB, BB);
> +    PredBB = SplitEdge(PredBB, BB, DT);
>       OldPredBranch = cast<BranchInst>(PredBB->getTerminator());
>     }
>   
> @@ -2244,6 +2280,8 @@ bool JumpThreadingPass::DuplicateCondBra
>   
>     // Remove the unconditional branch at the end of the PredBB block.
>     OldPredBranch->eraseFromParent();
> +  if (BB != PredBB)
> +    DT->deleteEdge(PredBB, BB);
>   
>     ++NumDupes;
>     return true;
> @@ -2309,6 +2347,7 @@ bool JumpThreadingPass::TryToUnfoldSelec
>         // Move the unconditional branch to NewBB.
>         PredTerm->removeFromParent();
>         NewBB->getInstList().insert(NewBB->end(), PredTerm);
> +      DT->insertEdge(NewBB, BB);
>         // Create a conditional branch and update PHI nodes.
>         BranchInst::Create(NewBB, BB, SI->getCondition(), Pred);
>         CondLHS->setIncomingValue(I, SI->getFalseValue());
> @@ -2316,6 +2355,7 @@ bool JumpThreadingPass::TryToUnfoldSelec
>         // The select is now dead.
>         SI->eraseFromParent();
>   
> +      DT->insertEdge(Pred, NewBB);
>         // Update any other PHI nodes in BB.
>         for (BasicBlock::iterator BI = BB->begin();
>              PHINode *Phi = dyn_cast<PHINode>(BI); ++BI)
> @@ -2393,7 +2433,7 @@ bool JumpThreadingPass::TryToUnfoldSelec
>         continue;
>       // Expand the select.
>       TerminatorInst *Term =
> -        SplitBlockAndInsertIfThen(SI->getCondition(), SI, false);
> +        SplitBlockAndInsertIfThen(SI->getCondition(), SI, false, nullptr, DT);
>       PHINode *NewPN = PHINode::Create(SI->getType(), 2, "", SI);
>       NewPN->addIncoming(SI->getTrueValue(), Term->getParent());
>       NewPN->addIncoming(SI->getFalseValue(), BB);
> @@ -2485,8 +2525,8 @@ bool JumpThreadingPass::ThreadGuard(Basi
>     if (!TrueDestIsSafe && !FalseDestIsSafe)
>       return false;
>   
> -  BasicBlock *UnguardedBlock = TrueDestIsSafe ? TrueDest : FalseDest;
> -  BasicBlock *GuardedBlock = FalseDestIsSafe ? TrueDest : FalseDest;
> +  BasicBlock *PredUnguardedBlock = TrueDestIsSafe ? TrueDest : FalseDest;
> +  BasicBlock *PredGuardedBlock = FalseDestIsSafe ? TrueDest : FalseDest;
>   
>     ValueToValueMapTy UnguardedMapping, GuardedMapping;
>     Instruction *AfterGuard = Guard->getNextNode();
> @@ -2495,17 +2535,28 @@ bool JumpThreadingPass::ThreadGuard(Basi
>       return false;
>     // Duplicate all instructions before the guard and the guard itself to the
>     // branch where implication is not proved.
> -  GuardedBlock = DuplicateInstructionsInSplitBetween(
> -      BB, GuardedBlock, AfterGuard, GuardedMapping);
> +  BasicBlock *GuardedBlock = DuplicateInstructionsInSplitBetween(
> +      BB, PredGuardedBlock, AfterGuard, GuardedMapping);
>     assert(GuardedBlock && "Could not create the guarded block?");
>     // Duplicate all instructions before the guard in the unguarded branch.
>     // Since we have successfully duplicated the guarded block and this block
>     // has fewer instructions, we expect it to succeed.
> -  UnguardedBlock = DuplicateInstructionsInSplitBetween(BB, UnguardedBlock,
> -                                                       Guard, UnguardedMapping);
> +  BasicBlock *UnguardedBlock = DuplicateInstructionsInSplitBetween(
> +      BB, PredUnguardedBlock, Guard, UnguardedMapping);
>     assert(UnguardedBlock && "Could not create the unguarded block?");
>     DEBUG(dbgs() << "Moved guard " << *Guard << " to block "
>                  << GuardedBlock->getName() << "\n");
> +  // DuplicateInstructionsInSplitBetween inserts a new block, BB.split, between
> +  // PredBB and BB. We need to perform two inserts and one delete in DT for each
> +  // of the above calls.
> +  DT->applyUpdates({// Guarded block split.
> +                    {DominatorTree::Delete, PredGuardedBlock, BB},
> +                    {DominatorTree::Insert, PredGuardedBlock, GuardedBlock},
> +                    {DominatorTree::Insert, GuardedBlock, BB},
> +                    // Unguarded block split.
> +                    {DominatorTree::Delete, PredUnguardedBlock, BB},
> +                    {DominatorTree::Insert, PredUnguardedBlock, UnguardedBlock},
> +                    {DominatorTree::Insert, UnguardedBlock, BB}});
>   
>     // Some instructions before the guard may still have uses. For them, we need
>     // to create Phi nodes merging their copies in both guarded and unguarded
>
> Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/Local.cpp Thu Sep 28 10:24:40 2017
> @@ -68,7 +68,8 @@ STATISTIC(NumRemoved, "Number of unreach
>   /// conditions and indirectbr addresses this might make dead if
>   /// DeleteDeadConditions is true.
>   bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
> -                                  const TargetLibraryInfo *TLI) {
> +                                  const TargetLibraryInfo *TLI,
> +                                  DominatorTree *DT) {
>     TerminatorInst *T = BB->getTerminator();
>     IRBuilder<> Builder(T);
>   
> @@ -95,6 +96,8 @@ bool llvm::ConstantFoldTerminator(BasicB
>         // Replace the conditional branch with an unconditional one.
>         Builder.CreateBr(Destination);
>         BI->eraseFromParent();
> +      if (DT && OldDest != Destination && OldDest != BB)
> +        DT->deleteEdge(BB, OldDest);
>         return true;
>       }
>   
> @@ -165,9 +168,17 @@ bool llvm::ConstantFoldTerminator(BasicB
>                             createBranchWeights(Weights));
>           }
>           // Remove this entry.
> -        DefaultDest->removePredecessor(SI->getParent());
> +        BasicBlock *ParentBB = SI->getParent();
> +        DefaultDest->removePredecessor(ParentBB);
>           i = SI->removeCase(i);
>           e = SI->case_end();
> +        if (DT && DefaultDest != ParentBB) {
> +          // DefaultDest may still be a successor of a non-default case.
> +          if (none_of(successors(ParentBB), [DefaultDest](BasicBlock *S) {
> +                return S == DefaultDest;
> +              }))
> +            DT->deleteEdge(ParentBB, DefaultDest);
> +        }
>           continue;
>         }
>   
> @@ -193,19 +204,29 @@ bool llvm::ConstantFoldTerminator(BasicB
>         // Insert the new branch.
>         Builder.CreateBr(TheOnlyDest);
>         BasicBlock *BB = SI->getParent();
> +      BasicBlock *TheOnlyDestCheck = TheOnlyDest;
> +      std::vector<DominatorTree::UpdateType> Updates;
>   
>         // Remove entries from PHI nodes which we no longer branch to...
>         for (BasicBlock *Succ : SI->successors()) {
>           // Found case matching a constant operand?
> -        if (Succ == TheOnlyDest)
> +        if (Succ == TheOnlyDest) {
>             TheOnlyDest = nullptr; // Don't modify the first branch to TheOnlyDest
> -        else
> +        } else {
>             Succ->removePredecessor(BB);
> +          if (DT && Succ != TheOnlyDestCheck && Succ != BB) {
> +            DominatorTree::UpdateType UT = {DominatorTree::Delete, BB, Succ};
> +            if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +              Updates.push_back(UT);
> +          }
> +        }
>         }
>   
>         // Delete the old switch.
>         Value *Cond = SI->getCondition();
>         SI->eraseFromParent();
> +      if (DT && !Updates.empty())
> +        DT->applyUpdates(Updates);
>         if (DeleteDeadConditions)
>           RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI);
>         return true;
> @@ -253,17 +274,30 @@ bool llvm::ConstantFoldTerminator(BasicB
>       if (BlockAddress *BA =
>             dyn_cast<BlockAddress>(IBI->getAddress()->stripPointerCasts())) {
>         BasicBlock *TheOnlyDest = BA->getBasicBlock();
> +      BasicBlock *TheOnlyDestCheck = TheOnlyDest;
> +      std::vector<DominatorTree::UpdateType> Updates;
>         // Insert the new branch.
>         Builder.CreateBr(TheOnlyDest);
>   
>         for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) {
> -        if (IBI->getDestination(i) == TheOnlyDest)
> +        if (IBI->getDestination(i) == TheOnlyDest) {
>             TheOnlyDest = nullptr;
> -        else
> -          IBI->getDestination(i)->removePredecessor(IBI->getParent());
> +        } else {
> +          BasicBlock *ParentBB = IBI->getParent();
> +          BasicBlock *DestBB = IBI->getDestination(i);
> +          DestBB->removePredecessor(ParentBB);
> +          if (DT && DestBB != TheOnlyDestCheck && DestBB != ParentBB) {
> +            DominatorTree::UpdateType UT = {DominatorTree::Delete, ParentBB,
> +                                            DestBB};
> +            if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +              Updates.push_back(UT);
> +          }
> +        }
>         }
>         Value *Address = IBI->getAddress();
>         IBI->eraseFromParent();
> +      if (DT && !Updates.empty())
> +        DT->applyUpdates(Updates);
>         if (DeleteDeadConditions)
>           RecursivelyDeleteTriviallyDeadInstructions(Address, TLI);
>   
> @@ -553,7 +587,8 @@ bool llvm::SimplifyInstructionsInBlock(B
>   ///
>   /// .. 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) {
> +void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
> +                                        DominatorTree *DT) {
>     // This only adjusts blocks with PHI nodes.
>     if (!isa<PHINode>(BB->begin()))
>       return;
> @@ -576,6 +611,8 @@ void llvm::RemovePredecessorAndSimplify(
>       // of the block.
>       if (PhiIt != OldPhiIt) PhiIt = &BB->front();
>     }
> +  if (DT && BB != Pred)
> +    DT->deleteEdge(Pred, BB);
>   }
>   
>   
> @@ -597,6 +634,23 @@ void llvm::MergeBasicBlockIntoOnlyPred(B
>     BasicBlock *PredBB = DestBB->getSinglePredecessor();
>     assert(PredBB && "Block doesn't have a single predecessor!");
>   
> +  // Collect all the edges that enter PredBB, discarding edges to itself and
> +  // duplicates. These dominator edges will be redirected to DestBB.
> +  std::vector<DominatorTree::UpdateType> Updates;
> +  if (DT)
> +    for (pred_iterator PI = pred_begin(PredBB), E = pred_end(PredBB); PI != E;
> +         ++PI) {
> +      if (*PI == PredBB)
> +        continue;
> +      DominatorTree::UpdateType UT = {DominatorTree::Delete, *PI, PredBB};
> +      if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end()) {
> +        Updates.push_back(UT);
> +        // DestBB cannot dominate itself.
> +        if (*PI != DestBB)
> +          Updates.push_back({DominatorTree::Insert, *PI, DestBB});
> +      }
> +    }
> +
>     // Zap anything that took the address of DestBB.  Not doing this will give the
>     // address an invalid value.
>     if (DestBB->hasAddressTaken()) {
> @@ -617,16 +671,25 @@ void llvm::MergeBasicBlockIntoOnlyPred(B
>   
>     // If the PredBB is the entry block of the function, move DestBB up to
>     // become the entry block after we erase PredBB.
> -  if (PredBB == &DestBB->getParent()->getEntryBlock())
> +  bool ReplacedEntryBB = false;
> +  if (PredBB == &DestBB->getParent()->getEntryBlock()) {
>       DestBB->moveAfter(PredBB);
> +    ReplacedEntryBB = true;
> +  }
>   
> -  if (DT) {
> -    BasicBlock *PredBBIDom = DT->getNode(PredBB)->getIDom()->getBlock();
> -    DT->changeImmediateDominator(DestBB, PredBBIDom);
> -    DT->eraseNode(PredBB);
> +  if (DT && !ReplacedEntryBB) {
> +    Updates.push_back({DominatorTree::Delete, PredBB, DestBB});
> +    DT->applyUpdates(Updates);
>     }
> +
>     // Nuke BB.
>     PredBB->eraseFromParent();
> +
> +  // 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.
> +  if (DT && ReplacedEntryBB)
> +    DT->recalculate(*(DestBB->getParent()));
>   }
>   
>   /// CanMergeValues - Return true if we can choose one of these values to use
> @@ -834,7 +897,8 @@ static void redirectValuesFromPredecesso
>   /// potential side-effect free 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 llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB) {
> +bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
> +                                                   DominatorTree *DT) {
>     assert(BB != &BB->getParent()->getEntryBlock() &&
>            "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!");
>   
> @@ -875,6 +939,20 @@ bool llvm::TryToSimplifyUncondBranchFrom
>   
>     DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);
>   
> +  // Collect all the edges that enter BB, discarding edges to itself and
> +  // duplicates. These dominator edges will be redirected to Succ.
> +  std::vector<DominatorTree::UpdateType> Updates;
> +  if (DT)
> +    for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
> +      if (*PI == BB)
> +        continue;
> +      DominatorTree::UpdateType UT = {DominatorTree::Delete, *PI, BB};
> +      if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end()) {
> +        Updates.push_back(UT);
> +        Updates.push_back({DominatorTree::Insert, *PI, Succ});
> +      }
> +    }
> +
>     if (isa<PHINode>(Succ->begin())) {
>       // If there is more than one pred of succ, and there are PHI nodes in
>       // the successor, then we need to add incoming edges for the PHI nodes
> @@ -909,16 +987,27 @@ bool llvm::TryToSimplifyUncondBranchFrom
>     // add the metadata to the branch instructions in the predecessors.
>     unsigned LoopMDKind = BB->getContext().getMDKindID("llvm.loop");
>     Instruction *TI = BB->getTerminator();
> -  if (TI)
> +  if (TI) {
>       if (MDNode *LoopMD = TI->getMetadata(LoopMDKind))
>         for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
>           BasicBlock *Pred = *PI;
>           Pred->getTerminator()->setMetadata(LoopMDKind, LoopMD);
>         }
> +    // Replace the terminator instruction with unreachable to ensure the CFG is
> +    // consistent. This is necessary for dominance to be correctly calculated.
> +    new UnreachableInst(BB->getContext(), TI);
> +    TI->eraseFromParent();
> +  }
>   
>     // Everything that jumped to BB now goes to Succ.
>     BB->replaceAllUsesWith(Succ);
>     if (!Succ->hasName()) Succ->takeName(BB);
> +
> +  if (DT) {
> +    Updates.push_back({DominatorTree::Delete, BB, Succ});
> +    DT->applyUpdates(Updates);
> +  }
> +
>     BB->eraseFromParent();              // Delete the old basic block.
>     return true;
>   }
> @@ -1399,13 +1488,19 @@ unsigned llvm::removeAllNonTerminatorAnd
>   }
>   
>   unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
> -                                   bool PreserveLCSSA) {
> +                                   bool PreserveLCSSA, DominatorTree *DT) {
>     BasicBlock *BB = I->getParent();
> +  std::vector<DominatorTree::UpdateType> Updates;
>     // Loop over all of the successors, removing BB's entry from any PHI
>     // nodes.
> -  for (BasicBlock *Successor : successors(BB))
> +  for (BasicBlock *Successor : successors(BB)) {
>       Successor->removePredecessor(BB, PreserveLCSSA);
> -
> +    if (DT && BB != Successor) {
> +      DominatorTree::UpdateType UT = {DominatorTree::Delete, BB, Successor};
> +      if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +        Updates.push_back(UT);
> +    }
> +  }
>     // Insert a call to llvm.trap right before this.  This turns the undefined
>     // behavior into a hard fail instead of falling through into random code.
>     if (UseLLVMTrap) {
> @@ -1425,11 +1520,13 @@ unsigned llvm::changeToUnreachable(Instr
>       BB->getInstList().erase(BBI++);
>       ++NumInstrsRemoved;
>     }
> +  if (DT && !Updates.empty())
> +    DT->applyUpdates(Updates);
>     return NumInstrsRemoved;
>   }
>   
>   /// changeToCall - Convert the specified invoke into a normal call.
> -static void changeToCall(InvokeInst *II) {
> +static void changeToCall(InvokeInst *II, DominatorTree *DT = nullptr) {
>     SmallVector<Value*, 8> Args(II->arg_begin(), II->arg_end());
>     SmallVector<OperandBundleDef, 1> OpBundles;
>     II->getOperandBundlesAsDefs(OpBundles);
> @@ -1442,11 +1539,16 @@ static void changeToCall(InvokeInst *II)
>     II->replaceAllUsesWith(NewCall);
>   
>     // Follow the call by a branch to the normal destination.
> -  BranchInst::Create(II->getNormalDest(), II);
> +  BasicBlock *NormalDestBB = II->getNormalDest();
> +  BranchInst::Create(NormalDestBB, II);
>   
>     // Update PHI nodes in the unwind destination
> -  II->getUnwindDest()->removePredecessor(II->getParent());
> +  BasicBlock *BB = II->getParent();
> +  BasicBlock *UnwindDestBB = II->getUnwindDest();
> +  UnwindDestBB->removePredecessor(BB);
>     II->eraseFromParent();
> +  if (DT && BB != UnwindDestBB && NormalDestBB != UnwindDestBB)
> +    DT->deleteEdge(BB, UnwindDestBB);
>   }
>   
>   BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
> @@ -1487,7 +1589,8 @@ BasicBlock *llvm::changeToInvokeAndSplit
>   }
>   
>   static bool markAliveBlocks(Function &F,
> -                            SmallPtrSetImpl<BasicBlock*> &Reachable) {
> +                            SmallPtrSetImpl<BasicBlock *> &Reachable,
> +                            DominatorTree *DT = nullptr) {
>   
>     SmallVector<BasicBlock*, 128> Worklist;
>     BasicBlock *BB = &F.front();
> @@ -1508,7 +1611,7 @@ static bool markAliveBlocks(Function &F,
>           if (II->getIntrinsicID() == Intrinsic::assume) {
>             if (match(II->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) {
>               // Don't insert a call to llvm.trap right before the unreachable.
> -            changeToUnreachable(II, false);
> +            changeToUnreachable(II, false, false, DT);
>               Changed = true;
>               break;
>             }
> @@ -1525,7 +1628,8 @@ static bool markAliveBlocks(Function &F,
>             // still be useful for widening.
>             if (match(II->getArgOperand(0), m_Zero()))
>               if (!isa<UnreachableInst>(II->getNextNode())) {
> -              changeToUnreachable(II->getNextNode(), /*UseLLVMTrap=*/ false);
> +              changeToUnreachable(II->getNextNode(), /*UseLLVMTrap=*/false,
> +                                  false, DT);
>                 Changed = true;
>                 break;
>               }
> @@ -1535,7 +1639,7 @@ static bool markAliveBlocks(Function &F,
>         if (auto *CI = dyn_cast<CallInst>(&I)) {
>           Value *Callee = CI->getCalledValue();
>           if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
> -          changeToUnreachable(CI, /*UseLLVMTrap=*/false);
> +          changeToUnreachable(CI, /*UseLLVMTrap=*/false, false, DT);
>             Changed = true;
>             break;
>           }
> @@ -1545,7 +1649,7 @@ static bool markAliveBlocks(Function &F,
>             // though.
>             if (!isa<UnreachableInst>(CI->getNextNode())) {
>               // Don't insert a call to llvm.trap right before the unreachable.
> -            changeToUnreachable(CI->getNextNode(), false);
> +            changeToUnreachable(CI->getNextNode(), false, false, DT);
>               Changed = true;
>             }
>             break;
> @@ -1564,7 +1668,7 @@ static bool markAliveBlocks(Function &F,
>           if (isa<UndefValue>(Ptr) ||
>               (isa<ConstantPointerNull>(Ptr) &&
>                SI->getPointerAddressSpace() == 0)) {
> -          changeToUnreachable(SI, true);
> +          changeToUnreachable(SI, true, false, DT);
>             Changed = true;
>             break;
>           }
> @@ -1576,16 +1680,19 @@ static bool markAliveBlocks(Function &F,
>         // Turn invokes that call 'nounwind' functions into ordinary calls.
>         Value *Callee = II->getCalledValue();
>         if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
> -        changeToUnreachable(II, true);
> +        changeToUnreachable(II, true, false, DT);
>           Changed = true;
>         } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
>           if (II->use_empty() && II->onlyReadsMemory()) {
>             // jump to the normal destination branch.
> +          BasicBlock *UnwindDestBB = II->getUnwindDest();
>             BranchInst::Create(II->getNormalDest(), II);
> -          II->getUnwindDest()->removePredecessor(II->getParent());
> +          UnwindDestBB->removePredecessor(II->getParent());
>             II->eraseFromParent();
> +          if (DT && BB != UnwindDestBB)
> +            DT->deleteEdge(BB, UnwindDestBB);
>           } else
> -          changeToCall(II);
> +          changeToCall(II, DT);
>           Changed = true;
>         }
>       } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Terminator)) {
> @@ -1628,7 +1735,7 @@ static bool markAliveBlocks(Function &F,
>         }
>       }
>   
> -    Changed |= ConstantFoldTerminator(BB, true);
> +    Changed |= ConstantFoldTerminator(BB, true, nullptr, DT);
>       for (BasicBlock *Successor : successors(BB))
>         if (Reachable.insert(Successor).second)
>           Worklist.push_back(Successor);
> @@ -1636,11 +1743,11 @@ static bool markAliveBlocks(Function &F,
>     return Changed;
>   }
>   
> -void llvm::removeUnwindEdge(BasicBlock *BB) {
> +void llvm::removeUnwindEdge(BasicBlock *BB, DominatorTree *DT) {
>     TerminatorInst *TI = BB->getTerminator();
>   
>     if (auto *II = dyn_cast<InvokeInst>(TI)) {
> -    changeToCall(II);
> +    changeToCall(II, DT);
>       return;
>     }
>   
> @@ -1668,15 +1775,19 @@ void llvm::removeUnwindEdge(BasicBlock *
>     UnwindDest->removePredecessor(BB);
>     TI->replaceAllUsesWith(NewTI);
>     TI->eraseFromParent();
> +  if (DT && BB != UnwindDest)
> +    DT->deleteEdge(BB, UnwindDest);
>   }
>   
>   /// removeUnreachableBlocks - Remove blocks that are not reachable, even
>   /// if they are in a dead cycle.  Return true if a change was made, false
>   /// otherwise. If `LVI` is passed, this function preserves LazyValueInfo
>   /// after modifying the CFG.
> -bool llvm::removeUnreachableBlocks(Function &F, LazyValueInfo *LVI) {
> +bool llvm::removeUnreachableBlocks(Function &F, LazyValueInfo *LVI,
> +                                   DominatorTree *DT) {
>     SmallPtrSet<BasicBlock*, 16> Reachable;
> -  bool Changed = markAliveBlocks(F, Reachable);
> +  bool Changed = markAliveBlocks(F, Reachable, DT);
> +  std::vector<DominatorTree::UpdateType> Updates;
>   
>     // If there are unreachable blocks in the CFG...
>     if (Reachable.size() == F.size())
> @@ -1685,6 +1796,8 @@ bool llvm::removeUnreachableBlocks(Funct
>     assert(Reachable.size() < F.size());
>     NumRemoved += F.size()-Reachable.size();
>   
> +  SmallPtrSet<TerminatorInst *, 4> TIRemoved;
> +
>     // Loop over all of the basic blocks that are not reachable, dropping all of
>     // their internal references...
>     for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB) {
> @@ -1692,13 +1805,35 @@ bool llvm::removeUnreachableBlocks(Funct
>         continue;
>   
>       for (BasicBlock *Successor : successors(&*BB))
> -      if (Reachable.count(Successor))
> +      if (Reachable.count(Successor)) {
>           Successor->removePredecessor(&*BB);
> +        if (DT && &*BB != Successor) {
> +          DominatorTree::UpdateType UT = {DominatorTree::Delete, &*BB,
> +                                          Successor};
> +          if (std::find(Updates.begin(), Updates.end(), UT) == Updates.end())
> +            Updates.push_back(UT);
> +        }
> +      }
> +
>       if (LVI)
>         LVI->eraseBlock(&*BB);
> +
> +    TerminatorInst *TI = BB->getTerminator();
> +    TIRemoved.insert(TI);
> +    new UnreachableInst(BB->getContext(), TI);
> +
>       BB->dropAllReferences();
>     }
>   
> +  // Remove all the terminator instructions after dropping all references. This
> +  // keeps the state of the CFG consistent and prevents asserts from circular
> +  // use counts in groups of unreachable basic blocks.
> +  for (TerminatorInst *TI : TIRemoved)
> +    TI->eraseFromParent();
> +
> +  if (DT && !Updates.empty())
> +    DT->applyUpdates(Updates);
> +
>     for (Function::iterator I = ++F.begin(); I != F.end();)
>       if (!Reachable.count(&*I))
>         I = F.getBasicBlockList().erase(I);
>
> Modified: llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll?rev=314435&r1=314434&r2=314435&view=diff
> ==============================================================================
> --- llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll (original)
> +++ llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll Thu Sep 28 10:24:40 2017
> @@ -19,10 +19,13 @@ entry:
>   ; CHECK-NEXT:     ; LatticeVal for: 'i32 %a' is: overdefined
>   ; CHECK-NEXT:     ; LatticeVal for: 'i32 %length' is: overdefined
>   ; CHECK-NEXT:     ; LatticeVal for: '  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%backedge' is: constantrange<0, 400>
> +; CHECK-NEXT:     ; LatticeVal for: '  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]' in BB: '%exit' is: constantrange<399, 400>
>   ; CHECK-NEXT:  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
>   ; CHECK-NEXT:     ; LatticeVal for: '  %iv.next = add nsw i32 %iv, 1' in BB: '%backedge' is: constantrange<1, 401>
> +; CHECK-NEXT:     ; LatticeVal for: '  %iv.next = add nsw i32 %iv, 1' in BB: '%exit' is: constantrange<400, 401>
>   ; CHECK-NEXT:  %iv.next = add nsw i32 %iv, 1
>   ; CHECK-NEXT:     ; LatticeVal for: '  %cont = icmp slt i32 %iv.next, 400' in BB: '%backedge' is: overdefined
> +; CHECK-NEXT:     ; LatticeVal for: '  %cont = icmp slt i32 %iv.next, 400' in BB: '%exit' is: constantrange<0, -1>
>   ; CHECK-NEXT:  %cont = icmp slt i32 %iv.next, 400
>   ; CHECK-NOT: loop
>   loop:
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list