[llvm] r322401 - [JumpThreading] Preservation of DT and LVI across the pass

Brian M. Rzycki via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 12 13:06:48 PST 2018


Author: brzycki
Date: Fri Jan 12 13:06:48 2018
New Revision: 322401

URL: http://llvm.org/viewvc/llvm-project?rev=322401&view=rev
Log:
[JumpThreading] Preservation of DT and LVI across the pass

Summary:
See D37528 for a previous (non-deferred) version of this
patch and its description.

Preserves dominance in a deferred manner using a new class
DeferredDominance. This reduces the performance impact of
updating the DominatorTree at every edge insertion and
deletion. A user may call DDT->flush() within JumpThreading
for an up-to-date DT. This patch currently has one flush()
at the end of runImpl() to ensure DT is preserved across
the pass.

LVI is also preserved to help subsequent passes such as
CorrelatedValuePropagation. LVI is simpler to maintain and
is done immediately (not deferred). The code to perform the
preversation was minimally altered and simply marked as
preserved for the PassManager to be informed.

This extends the analysis available to JumpThreading for
future enhancements such as threading across loop headers.

Reviewers: dberlin, kuhar, sebpop

Reviewed By: kuhar, sebpop

Subscribers: mgorny, dmgreen, kuba, rnk, rsmith, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D40146


Added:
    llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll
    llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll
    llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll
    llvm/trunk/unittests/IR/DeferredDominanceTest.cpp
Modified:
    llvm/trunk/include/llvm/IR/Dominators.h
    llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h
    llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
    llvm/trunk/include/llvm/Transforms/Utils/Local.h
    llvm/trunk/lib/IR/Dominators.cpp
    llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
    llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
    llvm/trunk/lib/Transforms/Utils/Local.cpp
    llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll
    llvm/trunk/unittests/IR/CMakeLists.txt

Modified: llvm/trunk/include/llvm/IR/Dominators.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Dominators.h?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Dominators.h (original)
+++ llvm/trunk/include/llvm/IR/Dominators.h Fri Jan 12 13:06:48 2018
@@ -290,6 +290,90 @@ public:
   void print(raw_ostream &OS, const Module *M = nullptr) const override;
 };
 
+//===-------------------------------------
+/// \brief Class to defer updates to a DominatorTree.
+///
+/// Definition: Applying updates to every edge insertion and deletion is
+/// expensive and not necessary. When one needs the DominatorTree for analysis
+/// they can request a flush() to perform a larger batch update. This has the
+/// advantage of the DominatorTree inspecting the set of updates to find
+/// duplicates or unnecessary subtree updates.
+///
+/// The scope of DeferredDominance operates at a Function level.
+///
+/// It is not necessary for the user to scrub the updates for duplicates or
+/// updates that point to the same block (Delete, BB_A, BB_A). Performance
+/// can be gained if the caller attempts to batch updates before submitting
+/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will
+/// occur.
+///
+/// It is required for the state of the LLVM IR to be applied *before*
+/// submitting updates. The update routines must analyze the current state
+/// between a pair of (From, To) basic blocks to determine if the update
+/// needs to be queued.
+/// Example (good):
+///     TerminatorInstructionBB->removeFromParent();
+///     DDT->deleteEdge(BB, Successor);
+/// Example (bad):
+///     DDT->deleteEdge(BB, Successor);
+///     TerminatorInstructionBB->removeFromParent();
+class DeferredDominance {
+public:
+  DeferredDominance(DominatorTree &DT_) : DT(DT_) {}
+
+  /// \brief Queues multiple updates and discards duplicates.
+  void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
+
+  /// \brief Helper method for a single edge insertion. It's almost always
+  /// better to batch updates and call applyUpdates to quickly remove duplicate
+  /// edges. This is best used when there is only a single insertion needed to
+  /// update Dominators.
+  void insertEdge(BasicBlock *From, BasicBlock *To);
+
+  /// \brief Helper method for a single edge deletion. It's almost always better
+  /// to batch updates and call applyUpdates to quickly remove duplicate edges.
+  /// This is best used when there is only a single deletion needed to update
+  /// Dominators.
+  void deleteEdge(BasicBlock *From, BasicBlock *To);
+
+  /// \brief Delays the deletion of a basic block until a flush() event.
+  void deleteBB(BasicBlock *DelBB);
+
+  /// \brief Returns true if DelBB is awaiting deletion at a flush() event.
+  bool pendingDeletedBB(BasicBlock *DelBB);
+
+  /// \brief Flushes all pending updates and block deletions. Returns a
+  /// correct DominatorTree reference to be used by the caller for analysis.
+  DominatorTree &flush();
+
+  /// \brief Drops all internal state and forces a (slow) recalculation of the
+  /// DominatorTree based on the current state of the LLVM IR in F. This should
+  /// only be used in corner cases such as the Entry block of F being deleted.
+  void recalculate(Function &F);
+
+  /// \brief Debug method to help view the state of pending updates.
+  LLVM_DUMP_METHOD void dump() const;
+
+private:
+  DominatorTree &DT;
+  SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
+  SmallPtrSet<BasicBlock *, 8> DeletedBBs;
+
+  /// Apply an update (Kind, From, To) to the internal queued updates. The
+  /// update is only added when determined to be necessary. Checks for
+  /// self-domination, unnecessary updates, duplicate requests, and balanced
+  /// pairs of requests are all performed. Returns true if the update is
+  /// queued and false if it is discarded.
+  bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
+                   BasicBlock *To);
+
+  /// Performs all pending basic block deletions. We have to defer the deletion
+  /// of these blocks until after the DominatorTree updates are applied. The
+  /// internal workings of the DominatorTree code expect every update's From
+  /// and To blocks to exist and to be a member of the same Function.
+  bool flushDelBB();
+};
+
 } // end namespace llvm
 
 #endif // LLVM_IR_DOMINATORS_H

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=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar/JumpThreading.h Fri Jan 12 13:06:48 2018
@@ -34,6 +34,7 @@ class BinaryOperator;
 class BranchInst;
 class CmpInst;
 class Constant;
+class DeferredDominance;
 class Function;
 class Instruction;
 class IntrinsicInst;
@@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInf
   TargetLibraryInfo *TLI;
   LazyValueInfo *LVI;
   AliasAnalysis *AA;
+  DeferredDominance *DDT;
   std::unique_ptr<BlockFrequencyInfo> BFI;
   std::unique_ptr<BranchProbabilityInfo> BPI;
   bool HasProfileData = false;
@@ -107,8 +109,8 @@ public:
 
   // Glue for old PM.
   bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
-               AliasAnalysis *AA_, bool HasProfileData_,
-               std::unique_ptr<BlockFrequencyInfo> BFI_,
+               AliasAnalysis *AA_, DeferredDominance *DDT_,
+               bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
                std::unique_ptr<BranchProbabilityInfo> BPI_);
 
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);

Modified: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h Fri Jan 12 13:06:48 2018
@@ -27,6 +27,7 @@ namespace llvm {
 
 class BlockFrequencyInfo;
 class BranchProbabilityInfo;
+class DeferredDominance;
 class DominatorTree;
 class Function;
 class Instruction;
@@ -38,7 +39,7 @@ class TargetLibraryInfo;
 class Value;
 
 /// Delete the specified block, which must have no predecessors.
-void DeleteDeadBlock(BasicBlock *BB);
+void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = 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

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=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Fri Jan 12 13:06:48 2018
@@ -117,7 +117,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,
+                            DeferredDominance *DDT = nullptr);
 
 //===----------------------------------------------------------------------===//
 //  Local dead code elimination.
@@ -171,18 +172,21 @@ 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,
+                                  DeferredDominance *DDT = 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);
+void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr,
+                                 DeferredDominance *DDT = 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);
+bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
+                                             DeferredDominance *DDT = 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
@@ -385,7 +389,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,
+                             DeferredDominance *DDT = nullptr);
 
 /// Convert the CallInst to InvokeInst with the specified unwind edge basic
 /// block.  This also splits the basic block where CI is located, because
@@ -400,12 +405,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, DeferredDominance *DDT = 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,
+                             DeferredDominance *DDT = nullptr);
 
 /// Combine the metadata of two instructions so that K can replace J
 ///

Modified: llvm/trunk/lib/IR/Dominators.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Dominators.cpp?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Dominators.cpp (original)
+++ llvm/trunk/lib/IR/Dominators.cpp Fri Jan 12 13:06:48 2018
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/IR/CFG.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/CommandLine.h"
@@ -389,3 +390,190 @@ void DominatorTreeWrapperPass::print(raw
   DT.print(OS);
 }
 
+//===----------------------------------------------------------------------===//
+//  DeferredDominance Implementation
+//===----------------------------------------------------------------------===//
+//
+// The implementation details of the DeferredDominance class which allows
+// one to queue updates to a DominatorTree.
+//
+//===----------------------------------------------------------------------===//
+
+/// \brief Queues multiple updates and discards duplicates.
+void DeferredDominance::applyUpdates(
+    ArrayRef<DominatorTree::UpdateType> Updates) {
+  SmallVector<DominatorTree::UpdateType, 8> Seen;
+  for (auto U : Updates)
+    // Avoid duplicates to applyUpdate() to save on analysis.
+    if (std::none_of(Seen.begin(), Seen.end(),
+                     [U](DominatorTree::UpdateType S) { return S == U; })) {
+      Seen.push_back(U);
+      applyUpdate(U.getKind(), U.getFrom(), U.getTo());
+    }
+}
+
+/// \brief Helper method for a single edge insertion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single insertion needed to update
+/// Dominators.
+void DeferredDominance::insertEdge(BasicBlock *From, BasicBlock *To) {
+  applyUpdate(DominatorTree::Insert, From, To);
+}
+
+/// \brief Helper method for a single edge deletion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single deletion needed to update
+/// Dominators.
+void DeferredDominance::deleteEdge(BasicBlock *From, BasicBlock *To) {
+  applyUpdate(DominatorTree::Delete, From, To);
+}
+
+/// \brief Delays the deletion of a basic block until a flush() event.
+void DeferredDominance::deleteBB(BasicBlock *DelBB) {
+  assert(DelBB && "Invalid push_back of nullptr DelBB.");
+  assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
+  // DelBB is unreachable and all its instructions are dead.
+  while (!DelBB->empty()) {
+    Instruction &I = DelBB->back();
+    // Replace used instructions with an arbitrary value (undef).
+    if (!I.use_empty())
+      I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
+    DelBB->getInstList().pop_back();
+  }
+  // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
+  // Child of Function F it must contain valid IR.
+  new UnreachableInst(DelBB->getContext(), DelBB);
+  DeletedBBs.insert(DelBB);
+}
+
+/// \brief Returns true if DelBB is awaiting deletion at a flush() event.
+bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) {
+  if (DeletedBBs.empty())
+    return false;
+  return DeletedBBs.count(DelBB) != 0;
+}
+
+/// \brief Flushes all pending updates and block deletions. Returns a
+/// correct DominatorTree reference to be used by the caller for analysis.
+DominatorTree &DeferredDominance::flush() {
+  // Updates to DT must happen before blocks are deleted below. Otherwise the
+  // DT traversal will encounter badref blocks and assert.
+  if (!PendUpdates.empty()) {
+    DT.applyUpdates(PendUpdates);
+    PendUpdates.clear();
+  }
+  flushDelBB();
+  return DT;
+}
+
+/// \brief Drops all internal state and forces a (slow) recalculation of the
+/// DominatorTree based on the current state of the LLVM IR in F. This should
+/// only be used in corner cases such as the Entry block of F being deleted.
+void DeferredDominance::recalculate(Function &F) {
+  // flushDelBB must be flushed before the recalculation. The state of the IR
+  // must be consistent before the DT traversal algorithm determines the
+  // actual DT.
+  if (flushDelBB() || !PendUpdates.empty()) {
+    DT.recalculate(F);
+    PendUpdates.clear();
+  }
+}
+
+/// \brief Debug method to help view the state of pending updates.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void DeferredDominance::dump() const {
+  raw_ostream &OS = llvm::dbgs();
+  OS << "PendUpdates:\n";
+  int I = 0;
+  for (auto U : PendUpdates) {
+    OS << "  " << I << " : ";
+    ++I;
+    if (U.getKind() == DominatorTree::Insert)
+      OS << "Insert, ";
+    else
+      OS << "Delete, ";
+    BasicBlock *From = U.getFrom();
+    if (From) {
+      auto S = From->getName();
+      if (!From->hasName())
+        S = "(no name)";
+      OS << S << "(" << From << "), ";
+    } else {
+      OS << "(badref), ";
+    }
+    BasicBlock *To = U.getTo();
+    if (To) {
+      auto S = To->getName();
+      if (!To->hasName())
+        S = "(no_name)";
+      OS << S << "(" << To << ")\n";
+    } else {
+      OS << "(badref)\n";
+    }
+  }
+  OS << "DeletedBBs:\n";
+  I = 0;
+  for (auto BB : DeletedBBs) {
+    OS << "  " << I << " : ";
+    ++I;
+    if (BB->hasName())
+      OS << BB->getName() << "(";
+    else
+      OS << "(no_name)(";
+    OS << BB << ")\n";
+  }
+}
+#endif
+
+/// Apply an update (Kind, From, To) to the internal queued updates. The
+/// update is only added when determined to be necessary. Checks for
+/// self-domination, unnecessary updates, duplicate requests, and balanced
+/// pairs of requests are all performed. Returns true if the update is
+/// queued and false if it is discarded.
+bool DeferredDominance::applyUpdate(DominatorTree::UpdateKind Kind,
+                                    BasicBlock *From, BasicBlock *To) {
+  if (From == To)
+    return false; // Cannot dominate self; discard update.
+
+  // Discard updates by inspecting the current state of successors of From.
+  // Since applyUpdate() must be called *after* the Terminator of From is
+  // altered we can determine if the update is unnecessary.
+  bool HasEdge = std::any_of(succ_begin(From), succ_end(From),
+                             [To](BasicBlock *B) { return B == To; });
+  if (Kind == DominatorTree::Insert && !HasEdge)
+    return false; // Unnecessary Insert: edge does not exist in IR.
+  if (Kind == DominatorTree::Delete && HasEdge)
+    return false; // Unnecessary Delete: edge still exists in IR.
+
+  // Analyze pending updates to determine if the update is unnecessary.
+  DominatorTree::UpdateType Update = {Kind, From, To};
+  DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
+                                          ? DominatorTree::Insert
+                                          : DominatorTree::Delete,
+                                      From, To};
+  for (auto I = PendUpdates.begin(), E = PendUpdates.end(); I != E; ++I) {
+    if (Update == *I)
+      return false; // Discard duplicate updates.
+    if (Invert == *I) {
+      // Update and Invert are both valid (equivalent to a no-op). Remove
+      // Invert from PendUpdates and discard the Update.
+      PendUpdates.erase(I);
+      return false;
+    }
+  }
+  PendUpdates.push_back(Update); // Save the valid update.
+  return true;
+}
+
+/// Performs all pending basic block deletions. We have to defer the deletion
+/// of these blocks until after the DominatorTree updates are applied. The
+/// internal workings of the DominatorTree code expect every update's From
+/// and To blocks to exist and to be a member of the same Function.
+bool DeferredDominance::flushDelBB() {
+  if (DeletedBBs.empty())
+    return false;
+  for (auto *BB : DeletedBBs)
+    BB->eraseFromParent();
+  DeletedBBs.clear();
+  return true;
+}

Modified: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp Fri Jan 12 13:06:48 2018
@@ -78,6 +78,7 @@ namespace {
     bool runOnFunction(Function &F) override;
 
     void getAnalysisUsage(AnalysisUsage &AU) const override {
+      AU.addRequired<DominatorTreeWrapperPass>();
       AU.addRequired<LazyValueInfoWrapperPass>();
       AU.addPreserved<GlobalsAAWrapperPass>();
     }
@@ -89,6 +90,7 @@ 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=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Fri Jan 12 13:06:48 2018
@@ -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)
@@ -278,8 +280,12 @@ 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();
+  DeferredDominance DDT(*DT);
   std::unique_ptr<BlockFrequencyInfo> BFI;
   std::unique_ptr<BranchProbabilityInfo> BPI;
   bool HasProfileData = F.hasProfileData();
@@ -289,12 +295,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, &DDT, 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;
 }
@@ -302,8 +307,12 @@ 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);
+  DeferredDominance DDT(DT);
 
   std::unique_ptr<BlockFrequencyInfo> BFI;
   std::unique_ptr<BranchProbabilityInfo> BPI;
@@ -313,25 +322,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, &DDT, 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_,
+                                DeferredDominance *DDT_, 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_;
+  DDT = DDT_;
   BFI.reset();
   BPI.reset();
   // When profile data is available, we need to update edge weights after
@@ -353,7 +365,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, DDT);
 
   FindLoopHeaders(F);
 
@@ -368,6 +380,10 @@ bool JumpThreadingPass::runImpl(Function
 
       ++I;
 
+      // Don't thread branches over a block that's slated for deletion.
+      if (DDT->pendingDeletedBB(BB))
+        continue;
+
       // If the block is trivially dead, zap it.  This eliminates the successor
       // edges which simplifies the CFG.
       if (pred_empty(BB) &&
@@ -376,7 +392,7 @@ bool JumpThreadingPass::runImpl(Function
               << "' with terminator: " << *BB->getTerminator() << '\n');
         LoopHeaders.erase(BB);
         LVI->eraseBlock(BB);
-        DeleteDeadBlock(BB);
+        DeleteDeadBlock(BB, DDT);
         Changed = true;
         continue;
       }
@@ -400,7 +416,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, DDT))
           Changed = true;
       }
     }
@@ -408,6 +424,7 @@ bool JumpThreadingPass::runImpl(Function
   } while (Changed);
 
   LoopHeaders.clear();
+  DDT->flush();
   return EverChanged;
 }
 
@@ -931,8 +948,8 @@ static bool hasAddressTakenAndUsed(Basic
 bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) {
   // If the block is trivially dead, just return and let the caller nuke it.
   // This simplifies other transformations.
-  if (pred_empty(BB) &&
-      BB != &BB->getParent()->getEntryBlock())
+  if (DDT->pendingDeletedBB(BB) ||
+      (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()))
     return false;
 
   // If this block has a single predecessor, and if that pred has a single
@@ -948,7 +965,7 @@ bool JumpThreadingPass::ProcessBlock(Bas
         LoopHeaders.insert(BB);
 
       LVI->eraseBlock(SinglePred);
-      MergeBasicBlockIntoOnlyPred(BB);
+      MergeBasicBlockIntoOnlyPred(BB, nullptr, DDT);
 
       // 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 +1048,23 @@ 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();
+    Updates.reserve(BBTerm->getNumSuccessors());
     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);
+      Updates.push_back({DominatorTree::Delete, BB, Succ});
     }
 
     DEBUG(dbgs() << "  In block '" << BB->getName()
           << "' folding undef terminator: " << *BBTerm << '\n');
     BranchInst::Create(BBTerm->getSuccessor(BestSucc), BBTerm);
     BBTerm->eraseFromParent();
+    DDT->applyUpdates(Updates);
     return true;
   }
 
@@ -1053,7 +1075,7 @@ bool JumpThreadingPass::ProcessBlock(Bas
     DEBUG(dbgs() << "  In block '" << BB->getName()
           << "' folding terminator: " << *BB->getTerminator() << '\n');
     ++NumFolds;
-    ConstantFoldTerminator(BB, true);
+    ConstantFoldTerminator(BB, true, nullptr, DDT);
     return true;
   }
 
@@ -1086,7 +1108,8 @@ 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 (CondCmp->use_empty())
@@ -1104,6 +1127,7 @@ bool JumpThreadingPass::ProcessBlock(Bas
             ConstantInt::getFalse(CondCmp->getType());
           ReplaceFoldableUses(CondCmp, CI);
         }
+        DDT->deleteEdge(BB, ToRemoveSucc);
         return true;
       }
 
@@ -1182,9 +1206,12 @@ bool JumpThreadingPass::ProcessImpliedCo
     Optional<bool> Implication =
         isImpliedCondition(PBI->getCondition(), Cond, DL, CondIsTrue);
     if (Implication) {
-      BI->getSuccessor(*Implication ? 1 : 0)->removePredecessor(BB);
-      BranchInst::Create(BI->getSuccessor(*Implication ? 0 : 1), BI);
+      BasicBlock *KeepSucc = BI->getSuccessor(*Implication ? 0 : 1);
+      BasicBlock *RemoveSucc = BI->getSuccessor(*Implication ? 1 : 0);
+      RemoveSucc->removePredecessor(BB);
+      BranchInst::Create(KeepSucc, BI);
       BI->eraseFromParent();
+      DDT->deleteEdge(BB, RemoveSucc);
       return true;
     }
     CurrentBB = CurrentPred;
@@ -1591,17 +1618,22 @@ bool JumpThreadingPass::ProcessThreadabl
     if (PredWithKnownDest ==
         (size_t)std::distance(pred_begin(BB), pred_end(BB))) {
       bool SeenFirstBranchToOnlyDest = false;
+      std::vector <DominatorTree::UpdateType> Updates;
+      Updates.reserve(BB->getTerminator()->getNumSuccessors() - 1);
       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.
+          Updates.push_back({DominatorTree::Delete, BB, SuccBB});
+        }
       }
 
       // Finally update the terminator.
       TerminatorInst *Term = BB->getTerminator();
       BranchInst::Create(OnlyDest, Term);
       Term->eraseFromParent();
+      DDT->applyUpdates(Updates);
 
       // If the condition is now dead due to the removal of the old terminator,
       // erase it.
@@ -1964,6 +1996,10 @@ bool JumpThreadingPass::ThreadEdge(Basic
       PredTerm->setSuccessor(i, NewBB);
     }
 
+  DDT->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.
@@ -1983,20 +2019,42 @@ bool JumpThreadingPass::ThreadEdge(Basic
 BasicBlock *JumpThreadingPass::SplitBlockPreds(BasicBlock *BB,
                                                ArrayRef<BasicBlock *> Preds,
                                                const char *Suffix) {
+  SmallVector<BasicBlock *, 2> NewBBs;
+
   // Collect the frequencies of all predecessors of BB, which will be used to
-  // update the edge weight on BB->SuccBB.
-  BlockFrequency PredBBFreq(0);
+  // update the edge weight of the result of splitting predecessors.
+  DenseMap<BasicBlock *, BlockFrequency> FreqMap;
   if (HasProfileData)
     for (auto Pred : Preds)
-      PredBBFreq += BFI->getBlockFreq(Pred) * BPI->getEdgeProbability(Pred, BB);
+      FreqMap.insert(std::make_pair(
+          Pred, BFI->getBlockFreq(Pred) * BPI->getEdgeProbability(Pred, BB)));
+
+  // In the case when BB is a LandingPad block we create 2 new predecessors
+  // instead of just one.
+  if (BB->isLandingPad()) {
+    std::string NewName = std::string(Suffix) + ".split-lp";
+    SplitLandingPadPredecessors(BB, Preds, Suffix, NewName.c_str(), NewBBs);
+  } else {
+    NewBBs.push_back(SplitBlockPredecessors(BB, Preds, Suffix));
+  }
 
-  BasicBlock *PredBB = SplitBlockPredecessors(BB, Preds, Suffix);
+  std::vector<DominatorTree::UpdateType> Updates;
+  Updates.reserve((2 * Preds.size()) + NewBBs.size());
+  for (auto NewBB : NewBBs) {
+    BlockFrequency NewBBFreq(0);
+    Updates.push_back({DominatorTree::Insert, NewBB, BB});
+    for (auto Pred : predecessors(NewBB)) {
+      Updates.push_back({DominatorTree::Delete, Pred, BB});
+      Updates.push_back({DominatorTree::Insert, Pred, NewBB});
+      if (HasProfileData) // Update frequencies between Pred -> NewBB.
+        NewBBFreq += FreqMap.lookup(Pred);
+    }
+    if (HasProfileData) // Apply the summed frequency to NewBB.
+      BFI->setBlockFreq(NewBB, NewBBFreq.getFrequency());
+  }
 
-  // Set the block frequency of the newly created PredBB, which is the sum of
-  // frequencies of Preds.
-  if (HasProfileData)
-    BFI->setBlockFreq(PredBB, PredBBFreq.getFrequency());
-  return PredBB;
+  DDT->applyUpdates(Updates);
+  return NewBBs[0];
 }
 
 bool JumpThreadingPass::doesBlockHaveProfileData(BasicBlock *BB) {
@@ -2140,6 +2198,7 @@ bool JumpThreadingPass::DuplicateCondBra
   }
 
   // And finally, do it!  Start by factoring the predecessors if needed.
+  std::vector<DominatorTree::UpdateType> Updates;
   BasicBlock *PredBB;
   if (PredBBs.size() == 1)
     PredBB = PredBBs[0];
@@ -2148,6 +2207,7 @@ bool JumpThreadingPass::DuplicateCondBra
           << " common predecessors.\n");
     PredBB = SplitBlockPreds(BB, PredBBs, ".thr_comm");
   }
+  Updates.push_back({DominatorTree::Delete, PredBB, BB});
 
   // Okay, we decided to do this!  Clone all the instructions in BB onto the end
   // of PredBB.
@@ -2160,7 +2220,11 @@ bool JumpThreadingPass::DuplicateCondBra
   BranchInst *OldPredBranch = dyn_cast<BranchInst>(PredBB->getTerminator());
 
   if (!OldPredBranch || !OldPredBranch->isUnconditional()) {
-    PredBB = SplitEdge(PredBB, BB);
+    BasicBlock *OldPredBB = PredBB;
+    PredBB = SplitEdge(OldPredBB, BB);
+    Updates.push_back({DominatorTree::Insert, OldPredBB, PredBB});
+    Updates.push_back({DominatorTree::Insert, PredBB, BB});
+    Updates.push_back({DominatorTree::Delete, OldPredBB, BB});
     OldPredBranch = cast<BranchInst>(PredBB->getTerminator());
   }
 
@@ -2202,6 +2266,10 @@ bool JumpThreadingPass::DuplicateCondBra
       // Otherwise, insert the new instruction into the block.
       New->setName(BI->getName());
       PredBB->getInstList().insert(OldPredBranch->getIterator(), New);
+      // Update Dominance from simplified New instruction operands.
+      for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
+        if (BasicBlock *SuccBB = dyn_cast<BasicBlock>(New->getOperand(i)))
+          Updates.push_back({DominatorTree::Insert, PredBB, SuccBB});
     }
   }
 
@@ -2257,6 +2325,7 @@ bool JumpThreadingPass::DuplicateCondBra
 
   // Remove the unconditional branch at the end of the PredBB block.
   OldPredBranch->eraseFromParent();
+  DDT->applyUpdates(Updates);
 
   ++NumDupes;
   return true;
@@ -2329,6 +2398,8 @@ bool JumpThreadingPass::TryToUnfoldSelec
       // The select is now dead.
       SI->eraseFromParent();
 
+      DDT->applyUpdates({{DominatorTree::Insert, NewBB, BB},
+                         {DominatorTree::Insert, Pred, NewBB}});
       // Update any other PHI nodes in BB.
       for (BasicBlock::iterator BI = BB->begin();
            PHINode *Phi = dyn_cast<PHINode>(BI); ++BI)
@@ -2407,11 +2478,25 @@ bool JumpThreadingPass::TryToUnfoldSelec
     // Expand the select.
     TerminatorInst *Term =
         SplitBlockAndInsertIfThen(SI->getCondition(), SI, false);
+    BasicBlock *SplitBB = SI->getParent();
+    BasicBlock *NewBB = Term->getParent();
     PHINode *NewPN = PHINode::Create(SI->getType(), 2, "", SI);
     NewPN->addIncoming(SI->getTrueValue(), Term->getParent());
     NewPN->addIncoming(SI->getFalseValue(), BB);
     SI->replaceAllUsesWith(NewPN);
     SI->eraseFromParent();
+    // NewBB and SplitBB are newly created blocks which require insertion.
+    std::vector<DominatorTree::UpdateType> Updates;
+    Updates.reserve((2 * SplitBB->getTerminator()->getNumSuccessors()) + 3);
+    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.
+    for (auto *Succ : successors(SplitBB)) {
+      Updates.push_back({DominatorTree::Delete, BB, Succ});
+      Updates.push_back({DominatorTree::Insert, SplitBB, Succ});
+    }
+    DDT->applyUpdates(Updates);
     return true;
   }
   return false;
@@ -2498,8 +2583,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();
@@ -2508,18 +2593,29 @@ 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 for each of
+  // the above calls to update Dominators.
+  DDT->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
   // branches. Those instructions that have no uses can be just removed.

Modified: llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp Fri Jan 12 13:06:48 2018
@@ -45,16 +45,22 @@
 
 using namespace llvm;
 
-void llvm::DeleteDeadBlock(BasicBlock *BB) {
+void llvm::DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT) {
   assert((pred_begin(BB) == pred_end(BB) ||
          // Can delete self loop.
          BB->getSinglePredecessor() == BB) && "Block is not dead!");
   TerminatorInst *BBTerm = BB->getTerminator();
+  std::vector<DominatorTree::UpdateType> Updates;
 
   // Loop through all of our successors and make sure they know that one
   // of their predecessors is going away.
-  for (BasicBlock *Succ : BBTerm->successors())
+  if (DDT)
+    Updates.reserve(BBTerm->getNumSuccessors());
+  for (BasicBlock *Succ : BBTerm->successors()) {
     Succ->removePredecessor(BB);
+    if (DDT)
+      Updates.push_back({DominatorTree::Delete, BB, Succ});
+  }
 
   // Zap all the instructions in the block.
   while (!BB->empty()) {
@@ -69,8 +75,12 @@ void llvm::DeleteDeadBlock(BasicBlock *B
     BB->getInstList().pop_back();
   }
 
-  // Zap the block!
-  BB->eraseFromParent();
+  if (DDT) {
+    DDT->applyUpdates(Updates);
+    DDT->deleteBB(BB); // Deferred deletion of BB.
+  } else {
+    BB->eraseFromParent(); // Zap the block!
+  }
 }
 
 void llvm::FoldSingleEntryPHINodes(BasicBlock *BB,

Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Fri Jan 12 13:06:48 2018
@@ -100,7 +100,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,
+                                  DeferredDominance *DDT) {
   TerminatorInst *T = BB->getTerminator();
   IRBuilder<> Builder(T);
 
@@ -123,6 +124,8 @@ bool llvm::ConstantFoldTerminator(BasicB
       // Replace the conditional branch with an unconditional one.
       Builder.CreateBr(Destination);
       BI->eraseFromParent();
+      if (DDT)
+        DDT->deleteEdge(BB, OldDest);
       return true;
     }
 
@@ -193,9 +196,12 @@ 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 (DDT)
+          DDT->deleteEdge(ParentBB, DefaultDest);
         continue;
       }
 
@@ -221,14 +227,20 @@ bool llvm::ConstantFoldTerminator(BasicB
       // Insert the new branch.
       Builder.CreateBr(TheOnlyDest);
       BasicBlock *BB = SI->getParent();
+      std::vector <DominatorTree::UpdateType> Updates;
+      if (DDT)
+        Updates.reserve(SI->getNumSuccessors() - 1);
 
       // 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 (DDT)
+            Updates.push_back({DominatorTree::Delete, BB, Succ});
+        }
       }
 
       // Delete the old switch.
@@ -236,6 +248,8 @@ bool llvm::ConstantFoldTerminator(BasicB
       SI->eraseFromParent();
       if (DeleteDeadConditions)
         RecursivelyDeleteTriviallyDeadInstructions(Cond, TLI);
+      if (DDT)
+        DDT->applyUpdates(Updates);
       return true;
     }
 
@@ -281,14 +295,23 @@ bool llvm::ConstantFoldTerminator(BasicB
     if (auto *BA =
           dyn_cast<BlockAddress>(IBI->getAddress()->stripPointerCasts())) {
       BasicBlock *TheOnlyDest = BA->getBasicBlock();
+      std::vector <DominatorTree::UpdateType> Updates;
+      if (DDT)
+        Updates.reserve(IBI->getNumDestinations() - 1);
+
       // 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 (DDT)
+            Updates.push_back({DominatorTree::Delete, ParentBB, DestBB});
+        }
       }
       Value *Address = IBI->getAddress();
       IBI->eraseFromParent();
@@ -303,6 +326,8 @@ bool llvm::ConstantFoldTerminator(BasicB
         new UnreachableInst(BB->getContext(), BB);
       }
 
+      if (DDT)
+        DDT->applyUpdates(Updates);
       return true;
     }
   }
@@ -579,7 +604,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,
+                                        DeferredDominance *DDT) {
   // This only adjusts blocks with PHI nodes.
   if (!isa<PHINode>(BB->begin()))
     return;
@@ -602,13 +628,18 @@ void llvm::RemovePredecessorAndSimplify(
     // of the block.
     if (PhiIt != OldPhiIt) PhiIt = &BB->front();
   }
+  if (DDT)
+    DDT->deleteEdge(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) {
+void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB, DominatorTree *DT,
+                                       DeferredDominance *DDT) {
+  assert(!(DT && DDT) && "Cannot call with both DT and DDT.");
+
   // If BB has single-entry PHI nodes, fold them.
   while (PHINode *PN = dyn_cast<PHINode>(DestBB->begin())) {
     Value *NewVal = PN->getIncomingValue(0);
@@ -621,6 +652,25 @@ void llvm::MergeBasicBlockIntoOnlyPred(B
   BasicBlock *PredBB = DestBB->getSinglePredecessor();
   assert(PredBB && "Block doesn't have a single predecessor!");
 
+  bool ReplaceEntryBB = false;
+  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.
+  std::vector <DominatorTree::UpdateType> Updates;
+  if (DDT && !ReplaceEntryBB) {
+    Updates.reserve(1 +
+                    (2 * std::distance(pred_begin(PredBB), pred_end(PredBB))));
+    Updates.push_back({DominatorTree::Delete, PredBB, DestBB});
+    for (auto I = pred_begin(PredBB), E = pred_end(PredBB); I != E; ++I) {
+      Updates.push_back({DominatorTree::Delete, *I, PredBB});
+      // This predecessor of PredBB may already have DestBB as a successor.
+      if (llvm::find(successors(*I), DestBB) == succ_end(*I))
+        Updates.push_back({DominatorTree::Insert, *I, DestBB});
+    }
+  }
+
   // Zap anything that took the address of DestBB.  Not doing this will give the
   // address an invalid value.
   if (DestBB->hasAddressTaken()) {
@@ -641,7 +691,7 @@ 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())
+  if (ReplaceEntryBB)
     DestBB->moveAfter(PredBB);
 
   if (DT) {
@@ -653,8 +703,19 @@ void llvm::MergeBasicBlockIntoOnlyPred(B
       DT->eraseNode(PredBB);
     }
   }
-  // Nuke BB.
-  PredBB->eraseFromParent();
+
+  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.
+  }
 }
 
 /// CanMergeValues - Return true if we can choose one of these values to use
@@ -861,7 +922,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,
+                                                   DeferredDominance *DDT) {
   assert(BB != &BB->getParent()->getEntryBlock() &&
          "TryToSimplifyUncondBranchFromEmptyBlock called on entry block!");
 
@@ -902,6 +964,19 @@ bool llvm::TryToSimplifyUncondBranchFrom
 
   DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);
 
+  std::vector<DominatorTree::UpdateType> Updates;
+  if (DDT) {
+    Updates.reserve(1 + (2 * std::distance(pred_begin(BB), pred_end(BB))));
+    Updates.push_back({DominatorTree::Delete, BB, Succ});
+    // All predecessors of BB will be moved to Succ.
+    for (auto I = pred_begin(BB), E = pred_end(BB); I != E; ++I) {
+      Updates.push_back({DominatorTree::Delete, *I, BB});
+      // This predecessor of BB may already have Succ as a successor.
+      if (llvm::find(successors(*I), Succ) == succ_end(*I))
+        Updates.push_back({DominatorTree::Insert, *I, 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
@@ -946,7 +1021,13 @@ bool llvm::TryToSimplifyUncondBranchFrom
   // Everything that jumped to BB now goes to Succ.
   BB->replaceAllUsesWith(Succ);
   if (!Succ->hasName()) Succ->takeName(BB);
-  BB->eraseFromParent();              // Delete the old basic block.
+
+  if (DDT) {
+    DDT->deleteBB(BB); // Deferred deletion of the old basic block.
+    DDT->applyUpdates(Updates);
+  } else {
+    BB->eraseFromParent(); // Delete the old basic block.
+  }
   return true;
 }
 
@@ -1444,13 +1525,19 @@ unsigned llvm::removeAllNonTerminatorAnd
 }
 
 unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
-                                   bool PreserveLCSSA) {
+                                   bool PreserveLCSSA, DeferredDominance *DDT) {
   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))
+  if (DDT)
+    Updates.reserve(BB->getTerminator()->getNumSuccessors());
+  for (BasicBlock *Successor : successors(BB)) {
     Successor->removePredecessor(BB, PreserveLCSSA);
-
+    if (DDT)
+      Updates.push_back({DominatorTree::Delete, BB, Successor});
+  }
   // 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) {
@@ -1470,11 +1557,13 @@ unsigned llvm::changeToUnreachable(Instr
     BB->getInstList().erase(BBI++);
     ++NumInstrsRemoved;
   }
+  if (DDT)
+    DDT->applyUpdates(Updates);
   return NumInstrsRemoved;
 }
 
 /// changeToCall - Convert the specified invoke into a normal call.
-static void changeToCall(InvokeInst *II) {
+static void changeToCall(InvokeInst *II, DeferredDominance *DDT = nullptr) {
   SmallVector<Value*, 8> Args(II->arg_begin(), II->arg_end());
   SmallVector<OperandBundleDef, 1> OpBundles;
   II->getOperandBundlesAsDefs(OpBundles);
@@ -1487,11 +1576,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 (DDT)
+    DDT->deleteEdge(BB, UnwindDestBB);
 }
 
 BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
@@ -1532,7 +1626,8 @@ BasicBlock *llvm::changeToInvokeAndSplit
 }
 
 static bool markAliveBlocks(Function &F,
-                            SmallPtrSetImpl<BasicBlock*> &Reachable) {
+                            SmallPtrSetImpl<BasicBlock*> &Reachable,
+                            DeferredDominance *DDT = nullptr) {
   SmallVector<BasicBlock*, 128> Worklist;
   BasicBlock *BB = &F.front();
   Worklist.push_back(BB);
@@ -1552,7 +1647,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, DDT);
             Changed = true;
             break;
           }
@@ -1569,7 +1664,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, DDT);
               Changed = true;
               break;
             }
@@ -1579,7 +1675,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, DDT);
           Changed = true;
           break;
         }
@@ -1589,7 +1685,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, DDT);
             Changed = true;
           }
           break;
@@ -1608,7 +1704,7 @@ static bool markAliveBlocks(Function &F,
         if (isa<UndefValue>(Ptr) ||
             (isa<ConstantPointerNull>(Ptr) &&
              SI->getPointerAddressSpace() == 0)) {
-          changeToUnreachable(SI, true);
+          changeToUnreachable(SI, true, false, DDT);
           Changed = true;
           break;
         }
@@ -1620,16 +1716,20 @@ 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, DDT);
         Changed = true;
       } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
         if (II->use_empty() && II->onlyReadsMemory()) {
           // jump to the normal destination branch.
-          BranchInst::Create(II->getNormalDest(), II);
-          II->getUnwindDest()->removePredecessor(II->getParent());
+          BasicBlock *NormalDestBB = II->getNormalDest();
+          BasicBlock *UnwindDestBB = II->getUnwindDest();
+          BranchInst::Create(NormalDestBB, II);
+          UnwindDestBB->removePredecessor(II->getParent());
           II->eraseFromParent();
+          if (DDT)
+            DDT->deleteEdge(BB, UnwindDestBB);
         } else
-          changeToCall(II);
+          changeToCall(II, DDT);
         Changed = true;
       }
     } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Terminator)) {
@@ -1675,7 +1775,7 @@ static bool markAliveBlocks(Function &F,
       }
     }
 
-    Changed |= ConstantFoldTerminator(BB, true);
+    Changed |= ConstantFoldTerminator(BB, true, nullptr, DDT);
     for (BasicBlock *Successor : successors(BB))
       if (Reachable.insert(Successor).second)
         Worklist.push_back(Successor);
@@ -1683,11 +1783,11 @@ static bool markAliveBlocks(Function &F,
   return Changed;
 }
 
-void llvm::removeUnwindEdge(BasicBlock *BB) {
+void llvm::removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT) {
   TerminatorInst *TI = BB->getTerminator();
 
   if (auto *II = dyn_cast<InvokeInst>(TI)) {
-    changeToCall(II);
+    changeToCall(II, DDT);
     return;
   }
 
@@ -1715,15 +1815,18 @@ void llvm::removeUnwindEdge(BasicBlock *
   UnwindDest->removePredecessor(BB);
   TI->replaceAllUsesWith(NewTI);
   TI->eraseFromParent();
+  if (DDT)
+    DDT->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,
+                                   DeferredDominance *DDT) {
   SmallPtrSet<BasicBlock*, 16> Reachable;
-  bool Changed = markAliveBlocks(F, Reachable);
+  bool Changed = markAliveBlocks(F, Reachable, DDT);
 
   // If there are unreachable blocks in the CFG...
   if (Reachable.size() == F.size())
@@ -1733,25 +1836,39 @@ bool llvm::removeUnreachableBlocks(Funct
   NumRemoved += F.size()-Reachable.size();
 
   // 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) {
-    if (Reachable.count(&*BB))
+  // their internal references. Update DDT and LVI if available.
+  std::vector <DominatorTree::UpdateType> Updates;
+  for (Function::iterator I = ++F.begin(), E = F.end(); I != E; ++I) {
+    auto *BB = &*I;
+    if (Reachable.count(BB))
       continue;
-
-    for (BasicBlock *Successor : successors(&*BB))
+    for (BasicBlock *Successor : successors(BB)) {
       if (Reachable.count(Successor))
-        Successor->removePredecessor(&*BB);
+        Successor->removePredecessor(BB);
+      if (DDT)
+        Updates.push_back({DominatorTree::Delete, BB, Successor});
+    }
     if (LVI)
-      LVI->eraseBlock(&*BB);
+      LVI->eraseBlock(BB);
     BB->dropAllReferences();
   }
 
-  for (Function::iterator I = ++F.begin(); I != F.end();)
-    if (!Reachable.count(&*I))
-      I = F.getBasicBlockList().erase(I);
-    else
+  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.
       ++I;
+    } else {
+      I = F.getBasicBlockList().erase(I);
+    }
+  }
 
+  if (DDT)
+    DDT->applyUpdates(Updates);
   return true;
 }
 

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=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll (original)
+++ llvm/trunk/test/Analysis/LazyValueAnalysis/lvi-after-jumpthreading.ll Fri Jan 12 13:06:48 2018
@@ -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:

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll?rev=322401&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash.ll Fri Jan 12 13:06:48 2018
@@ -0,0 +1,265 @@
+; RUN: opt < %s -jump-threading -disable-output
+
+%struct.ham = type { i8, i8, i16, i32 }
+%struct.zot = type { i32 (...)** }
+%struct.quux.0 = type { %struct.wombat }
+%struct.wombat = type { %struct.zot }
+
+ at global = external global %struct.ham*, align 8
+ at global.1 = external constant i8*
+
+declare i32 @wombat.2()
+
+define void @blam() {
+bb:
+  %tmp = load i32, i32* undef
+  %tmp1 = icmp eq i32 %tmp, 0
+  br i1 %tmp1, label %bb11, label %bb2
+
+bb2:
+  %tmp3 = tail call i32 @wombat.2()
+  switch i32 %tmp3, label %bb4 [
+    i32 0, label %bb5
+    i32 1, label %bb7
+    i32 2, label %bb7
+    i32 3, label %bb11
+  ]
+
+bb4:
+  br label %bb7
+
+bb5:
+  %tmp6 = tail call i32 @wombat.2()
+  br label %bb7
+
+bb7:
+  %tmp8 = phi i32 [ 0, %bb5 ], [ 1, %bb4 ], [ 2, %bb2 ], [ 2, %bb2 ]
+  %tmp9 = icmp eq i32 %tmp8, 0
+  br i1 %tmp9, label %bb11, label %bb10
+
+bb10:
+  ret void
+
+bb11:
+  ret void
+}
+
+define void @spam(%struct.ham* %arg) {
+bb:
+  %tmp = load i8, i8* undef, align 8
+  switch i8 %tmp, label %bb11 [
+    i8 1, label %bb11
+    i8 2, label %bb11
+    i8 3, label %bb1
+    i8 4, label %bb1
+  ]
+
+bb1:
+  br label %bb2
+
+bb2:
+  %tmp3 = phi i32 [ 0, %bb1 ], [ %tmp3, %bb8 ]
+  br label %bb4
+
+bb4:
+  %tmp5 = load i8, i8* undef, align 8
+  switch i8 %tmp5, label %bb11 [
+    i8 0, label %bb11
+    i8 1, label %bb10
+    i8 2, label %bb10
+    i8 3, label %bb6
+    i8 4, label %bb6
+  ]
+
+bb6:
+  br label %bb7
+
+bb7:
+  br i1 undef, label %bb8, label %bb10
+
+bb8:
+  %tmp9 = icmp eq %struct.ham* undef, %arg
+  br i1 %tmp9, label %bb10, label %bb2
+
+bb10:
+  switch i32 %tmp3, label %bb4 [
+    i32 0, label %bb14
+    i32 1, label %bb11
+    i32 2, label %bb12
+  ]
+
+bb11:
+  unreachable
+
+bb12:
+  %tmp13 = load %struct.ham*, %struct.ham** undef
+  br label %bb14
+
+bb14:
+  %tmp15 = phi %struct.ham* [ %tmp13, %bb12 ], [ null, %bb10 ]
+  br label %bb16
+
+bb16:
+  %tmp17 = load i8, i8* undef, align 8
+  switch i8 %tmp17, label %bb11 [
+    i8 0, label %bb11
+    i8 11, label %bb18
+    i8 12, label %bb18
+  ]
+
+bb18:
+  br label %bb19
+
+bb19:
+  br label %bb20
+
+bb20:
+  %tmp21 = load %struct.ham*, %struct.ham** undef
+  switch i8 undef, label %bb22 [
+    i8 0, label %bb4
+    i8 11, label %bb10
+    i8 12, label %bb10
+  ]
+
+bb22:
+  br label %bb23
+
+bb23:
+  %tmp24 = icmp eq %struct.ham* %tmp21, null
+  br i1 %tmp24, label %bb35, label %bb25
+
+bb25:
+  %tmp26 = icmp eq %struct.ham* %tmp15, null
+  br i1 %tmp26, label %bb34, label %bb27
+
+bb27:
+  %tmp28 = load %struct.ham*, %struct.ham** undef
+  %tmp29 = icmp eq %struct.ham* %tmp28, %tmp21
+  br i1 %tmp29, label %bb35, label %bb30
+
+bb30:
+  br label %bb31
+
+bb31:
+  %tmp32 = load i8, i8* undef, align 8
+  %tmp33 = icmp eq i8 %tmp32, 0
+  br i1 %tmp33, label %bb31, label %bb34
+
+bb34:
+  br label %bb35
+
+bb35:
+  %tmp36 = phi i1 [ true, %bb34 ], [ false, %bb23 ], [ true, %bb27 ]
+  br label %bb37
+
+bb37:
+  %tmp38 = icmp eq %struct.ham* %tmp15, null
+  br i1 %tmp38, label %bb39, label %bb41
+
+bb39:
+  %tmp40 = load %struct.ham*, %struct.ham** @global
+  br label %bb41
+
+bb41:
+  %tmp42 = select i1 %tmp36, %struct.ham* undef, %struct.ham* undef
+  ret void
+}
+
+declare i32 @foo(...)
+
+define void @zot() align 2 personality i8* bitcast (i32 (...)* @foo to i8*) {
+bb:
+  invoke void @bar()
+          to label %bb1 unwind label %bb3
+
+bb1:
+  invoke void @bar()
+          to label %bb2 unwind label %bb4
+
+bb2:
+  invoke void @bar()
+          to label %bb6 unwind label %bb17
+
+bb3:
+  %tmp = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb4:
+  %tmp5 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb6:
+  invoke void @bar()
+          to label %bb7 unwind label %bb19
+
+bb7:
+  invoke void @bar()
+          to label %bb10 unwind label %bb8
+
+bb8:
+  %tmp9 = landingpad { i8*, i32 }
+          cleanup
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb10:
+  %tmp11 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp12 = invoke i32 %tmp11(%struct.zot* nonnull undef)
+          to label %bb13 unwind label %bb21
+
+bb13:
+  invoke void @bar()
+          to label %bb14 unwind label %bb23
+
+bb14:
+  %tmp15 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp16 = invoke i32 %tmp15(%struct.zot* nonnull undef)
+          to label %bb26 unwind label %bb23
+
+bb17:
+  %tmp18 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb19:
+  %tmp20 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb21:
+  %tmp22 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  unreachable
+
+bb23:
+  %tmp24 = phi %struct.quux.0* [ null, %bb26 ], [ null, %bb14 ], [ undef, %bb13 ]
+  %tmp25 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @global.1 to i8*)
+          catch i8* null
+  br label %bb30
+
+bb26:
+  %tmp27 = load i32 (%struct.zot*)*, i32 (%struct.zot*)** undef, align 8
+  %tmp28 = invoke i32 %tmp27(%struct.zot* nonnull undef)
+          to label %bb29 unwind label %bb23
+
+bb29:
+  unreachable
+
+bb30:
+  %tmp31 = icmp eq %struct.quux.0* %tmp24, null
+  br i1 %tmp31, label %bb32, label %bb29
+
+bb32:
+  unreachable
+}
+
+declare void @bar()

Added: llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll?rev=322401&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/ddt-crash2.ll Fri Jan 12 13:06:48 2018
@@ -0,0 +1,40 @@
+; RUN: opt < %s -jump-threading -disable-output
+
+%struct.aaa = type { i8 }
+
+define void @chrome(%struct.aaa* noalias sret %arg) local_unnamed_addr #0 align 2 personality i8* bitcast (i32 (...)* @chrome2 to i8*) {
+bb:
+  %tmp = load i32, i32* undef, align 4
+  %tmp1 = icmp eq i32 %tmp, 0
+  br i1 %tmp1, label %bb2, label %bb13
+
+bb2:
+  %tmp3 = getelementptr inbounds %struct.aaa, %struct.aaa* %arg, i64 0, i32 0
+  %tmp4 = load i8, i8* %tmp3, align 1
+  %tmp5 = icmp eq i8 %tmp4, 0
+  br i1 %tmp5, label %bb6, label %bb7
+
+bb6:
+  store i8 0, i8* %tmp3, align 1
+  br label %bb7
+
+bb7:
+  %tmp8 = load i8, i8* %tmp3, align 1
+  %tmp9 = icmp ne i8 %tmp8, 0
+  %tmp10 = select i1 %tmp9, i1 true, i1 false
+  br i1 %tmp10, label %bb12, label %bb11
+
+bb11:
+  br label %bb12
+
+bb12:
+  br i1 %tmp9, label %bb14, label %bb13
+
+bb13:
+  unreachable
+
+bb14:
+  ret void
+}
+
+declare i32 @chrome2(...)

Added: llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll?rev=322401&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/lvi-tristate.ll Fri Jan 12 13:06:48 2018
@@ -0,0 +1,50 @@
+; RUN: opt -jump-threading -simplifycfg -S < %s | FileCheck %s
+; CHECK-NOT: bb6:
+; CHECK-NOT: bb7:
+; CHECK-NOT: bb8:
+; CHECK-NOT: bb11:
+; CHECK-NOT: bb12:
+; CHECK: bb:
+; CHECK: bb2:
+; CHECK: bb4:
+; CHECK: bb10:
+; CHECK: bb13:
+declare void @ham()
+
+define void @hoge() {
+bb:
+  %tmp = and i32 undef, 1073741823
+  %tmp1 = icmp eq i32 %tmp, 2
+  br i1 %tmp1, label %bb12, label %bb2
+
+bb2:
+  %tmp3 = icmp eq i32 %tmp, 3
+  br i1 %tmp3, label %bb13, label %bb4
+
+bb4:
+  %tmp5 = icmp eq i32 %tmp, 5
+  br i1 %tmp5, label %bb6, label %bb7
+
+bb6:
+  tail call void @ham()
+  br label %bb7
+
+bb7:
+  br i1 %tmp3, label %bb13, label %bb8
+
+bb8:
+  %tmp9 = icmp eq i32 %tmp, 4
+  br i1 %tmp9, label %bb13, label %bb10
+
+bb10:
+  br i1 %tmp9, label %bb11, label %bb13
+
+bb11:
+  br label %bb13
+
+bb12:
+  br label %bb2
+
+bb13:
+  ret void
+}

Modified: llvm/trunk/unittests/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=322401&r1=322400&r2=322401&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/CMakeLists.txt (original)
+++ llvm/trunk/unittests/IR/CMakeLists.txt Fri Jan 12 13:06:48 2018
@@ -15,6 +15,7 @@ set(IRSources
   ConstantsTest.cpp
   DebugInfoTest.cpp
   DebugTypeODRUniquingTest.cpp
+  DeferredDominanceTest.cpp
   DominatorTreeTest.cpp
   DominatorTreeBatchUpdatesTest.cpp
   FunctionTest.cpp

Added: llvm/trunk/unittests/IR/DeferredDominanceTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/DeferredDominanceTest.cpp?rev=322401&view=auto
==============================================================================
--- llvm/trunk/unittests/IR/DeferredDominanceTest.cpp (added)
+++ llvm/trunk/unittests/IR/DeferredDominanceTest.cpp Fri Jan 12 13:06:48 2018
@@ -0,0 +1,344 @@
+//===- llvm/unittests/IR/DeferredDominanceTest.cpp - DDT unit tests -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
+                                              StringRef ModuleStr) {
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
+  assert(M && "Bad LLVM IR?");
+  return M;
+}
+
+TEST(DeferredDominance, BasicOperations) {
+  StringRef FuncName = "f";
+  StringRef ModuleString =
+      "define i32 @f(i32 %i, i32 *%p) {\n"
+      " bb0:\n"
+      "   store i32 %i, i32 *%p\n"
+      "   switch i32 %i, label %bb1 [\n"
+      "     i32 0, label %bb2\n"
+      "     i32 1, label %bb2\n"
+      "     i32 2, label %bb3\n"
+      "   ]\n"
+      " bb1:\n"
+      "   ret i32 1\n"
+      " bb2:\n"
+      "   ret i32 2\n"
+      " bb3:\n"
+      "   ret i32 3\n"
+      "}\n";
+  // Make the module.
+  LLVMContext Context;
+  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+  Function *F = M->getFunction(FuncName);
+  ASSERT_NE(F, nullptr) << "Couldn't get function " << FuncName << ".";
+
+  // Make the DDT.
+  DominatorTree DT(*F);
+  DeferredDominance DDT(DT);
+  ASSERT_TRUE(DDT.flush().verify());
+
+  Function::iterator FI = F->begin();
+  BasicBlock *BB0 = &*FI++;
+  BasicBlock *BB1 = &*FI++;
+  BasicBlock *BB2 = &*FI++;
+  BasicBlock *BB3 = &*FI++;
+
+  // Test discards of invalid self-domination updates. These use the single
+  // short-hand interface but are still queued inside DDT.
+  DDT.deleteEdge(BB0, BB0);
+  DDT.insertEdge(BB1, BB1);
+
+  // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
+  // entries are discarded.
+  std::vector<DominatorTree::UpdateType> Updates;
+  Updates.reserve(4);
+  Updates.push_back({DominatorTree::Delete, BB0, BB3});
+  Updates.push_back({DominatorTree::Delete, BB0, BB3});
+
+  // Unnecessary Insert: no edge bb1 -> bb2 after change to bb0.
+  Updates.push_back({DominatorTree::Insert, BB1, BB2});
+  // Unnecessary Delete: edge exists bb0 -> bb1 after change to bb0.
+  Updates.push_back({DominatorTree::Delete, BB0, BB1});
+
+  // CFG Change: remove edge bb0 -> bb3 and one duplicate edge bb0 -> bb2.
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
+  BB0->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
+
+  // Deletion of a BasicBlock is an immediate event. We remove all uses to the
+  // contained Instructions and change the Terminator to "unreachable" when
+  // queued for deletion. Its parent is still F until DDT.flush() is called. We
+  // don't defer this action because it can cause problems for other transforms
+  // or analysis as it's part of the actual CFG. We only defer updates to the
+  // DominatorTree. This code will crash if it is placed before the
+  // BranchInst::Create() call above.
+  ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB3));
+  DDT.deleteBB(BB3);
+  EXPECT_TRUE(DDT.pendingDeletedBB(BB3));
+  ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
+  EXPECT_EQ(BB3->getParent(), F);
+
+  // Verify. Updates to DDT must be applied *after* all changes to the CFG
+  // (including block deletion).
+  DDT.applyUpdates(Updates);
+  ASSERT_TRUE(DDT.flush().verify());
+}
+
+TEST(DeferredDominance, PairedUpdate) {
+  StringRef FuncName = "f";
+  StringRef ModuleString =
+      "define i32 @f(i32 %i, i32 *%p) {\n"
+      " bb0:\n"
+      "   store i32 %i, i32 *%p\n"
+      "   switch i32 %i, label %bb1 [\n"
+      "     i32 0, label %bb2\n"
+      "     i32 1, label %bb2\n"
+      "   ]\n"
+      " bb1:\n"
+      "   ret i32 1\n"
+      " bb2:\n"
+      "   ret i32 2\n"
+      "}\n";
+  // Make the module.
+  LLVMContext Context;
+  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+  Function *F = M->getFunction(FuncName);
+  ASSERT_NE(F, nullptr) << "Couldn't get function " << FuncName << ".";
+
+  // Make the DDT.
+  DominatorTree DT(*F);
+  DeferredDominance DDT(DT);
+  ASSERT_TRUE(DDT.flush().verify());
+
+  Function::iterator FI = F->begin();
+  BasicBlock *BB0 = &*FI++;
+  BasicBlock *BB1 = &*FI++;
+  BasicBlock *BB2 = &*FI++;
+
+  // CFG Change: only edge from bb0 is bb0 -> bb1.
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
+  BB0->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB1, BB0);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
+
+  // Must be done after the CFG change. The applyUpdate() routine analyzes the
+  // current state of the CFG.
+  DDT.deleteEdge(BB0, BB2);
+
+  // CFG Change: bb0 now has bb0 -> bb1 and bb0 -> bb2.
+  // With this change no dominance has been altered from the original IR. DT
+  // doesn't care if the type of TerminatorInstruction changed, only if the
+  // unique edges have.
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
+  BB0->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB1, BB2, ConstantInt::getTrue(F->getContext()), BB0);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
+
+  // Must be done after the CFG change. The applyUpdate() routine analyzes the
+  // current state of the CFG. This DDT update pairs with the previous one and
+  // is cancelled out before ever applying updates to DT.
+  DDT.insertEdge(BB0, BB2);
+
+  // Test the empty DeletedBB list.
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB0));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB1));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB2));
+
+  // The DT has no changes, this flush() simply returns a reference to the
+  // internal DT calculated at the beginning of this test.
+  ASSERT_TRUE(DDT.flush().verify());
+}
+
+TEST(DeferredDominance, ReplaceEntryBB) {
+  StringRef FuncName = "f";
+  StringRef ModuleString =
+      "define i32 @f() {\n"
+      "bb0:\n"
+      "   br label %bb1\n"
+      " bb1:\n"
+      "   ret i32 1\n"
+      "}\n";
+  // Make the module.
+  LLVMContext Context;
+  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+  Function *F = M->getFunction(FuncName);
+  ASSERT_NE(F, nullptr) << "Couldn't get function " << FuncName << ".";
+
+  // Make the DDT.
+  DominatorTree DT(*F);
+  DeferredDominance DDT(DT);
+  ASSERT_TRUE(DDT.flush().verify());
+
+  Function::iterator FI = F->begin();
+  BasicBlock *BB0 = &*FI++;
+  BasicBlock *BB1 = &*FI++;
+
+  // Add a block as the new function entry BB. We also link it to BB0.
+  BasicBlock *NewEntry =
+      BasicBlock::Create(F->getContext(), "new_entry", F, BB0);
+  BranchInst::Create(BB0, NewEntry);
+  EXPECT_EQ(F->begin()->getName(), NewEntry->getName());
+  EXPECT_TRUE(&F->getEntryBlock() == NewEntry);
+
+  // Insert the new edge between new_eentry -> bb0. Without this the
+  // recalculate() call below will not actually recalculate the DT as there
+  // are no changes pending and no blocks deleted.
+  DDT.insertEdge(NewEntry, BB0);
+
+  // Changing the Entry BB requires a full recalulation.
+  DDT.recalculate(*F);
+  ASSERT_TRUE(DDT.flush().verify());
+
+  // CFG Change: remove new_edge -> bb0 and redirect to new_edge -> bb1.
+  EXPECT_EQ(NewEntry->getTerminator()->getNumSuccessors(), 1u);
+  NewEntry->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB1, NewEntry);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
+
+  // Update the DDT. At this point bb0 now has no predecessors but is still a
+  // Child of F.
+  DDT.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
+                    {DominatorTree::Insert, NewEntry, BB1}});
+  ASSERT_TRUE(DDT.flush().verify());
+
+  // Now remove bb0 from F.
+  ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB0));
+  DDT.deleteBB(BB0);
+  EXPECT_TRUE(DDT.pendingDeletedBB(BB0));
+  ASSERT_TRUE(isa<UnreachableInst>(BB0->getTerminator()));
+  EXPECT_EQ(BB0->getParent(), F);
+
+  // Perform a full recalculation of the DDT. It is not necessary here but we
+  // do this to test the case when there are no pending DT updates but there are
+  // pending deleted BBs.
+  DDT.recalculate(*F);
+  ASSERT_TRUE(DDT.flush().verify());
+}
+
+TEST(DeferredDominance, InheritedPreds) {
+  StringRef FuncName = "f";
+  StringRef ModuleString =
+      "define i32 @f(i32 %i, i32 *%p) {\n"
+      " bb0:\n"
+      "   store i32 %i, i32 *%p\n"
+      "   switch i32 %i, label %bb1 [\n"
+      "     i32 2, label %bb2\n"
+      "     i32 3, label %bb3\n"
+      "   ]\n"
+      " bb1:\n"
+      "   br label %bb3\n"
+      " bb2:\n"
+      "   br label %bb3\n"
+      " bb3:\n"
+      "   ret i32 3\n"
+      "}\n";
+  // Make the module.
+  LLVMContext Context;
+  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+  Function *F = M->getFunction(FuncName);
+  ASSERT_NE(F, nullptr) << "Couldn't get function " << FuncName << ".";
+
+  // Make the DDT.
+  DominatorTree DT(*F);
+  DeferredDominance DDT(DT);
+  ASSERT_TRUE(DDT.flush().verify());
+
+  Function::iterator FI = F->begin();
+  BasicBlock *BB0 = &*FI++;
+  BasicBlock *BB1 = &*FI++;
+  BasicBlock *BB2 = &*FI++;
+  BasicBlock *BB3 = &*FI++;
+
+  // There are several CFG locations where we have:
+  //
+  //   pred1..predN
+  //    |        |
+  //    +> curr <+    converted into:   pred1..predN curr
+  //        |                            |        |
+  //        v                            +> succ <+
+  //       succ
+  //
+  // There is a specific shape of this we have to be careful of:
+  //
+  //   pred1..predN
+  //   ||        |
+  //   |+> curr <+    converted into:   pred1..predN curr
+  //   |    |                            |        |
+  //   |    v                            +> succ <+
+  //   +-> succ
+  //
+  // While the final CFG form is functionally identical the updates to
+  // DDT are not. In the first case we must have DDT.insertEdge(Pred1, Succ)
+  // while in the latter case we must *NOT* have DDT.insertEdge(Pred1, Succ).
+
+  // CFG Change: bb0 now only has bb0 -> bb1 and bb0 -> bb3. We are preparing to
+  // remove bb2.
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
+  BB0->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB1, BB3, ConstantInt::getTrue(F->getContext()), BB0);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
+
+  // Remove bb2 from F. This has to happen before the call to applyUpdates() for
+  // DDT to detect there is no longer an edge between bb2 -> bb3. The deleteBB()
+  // method converts bb2's TI into "unreachable".
+  ASSERT_FALSE(isa<UnreachableInst>(BB2->getTerminator()));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB2));
+  DDT.deleteBB(BB2);
+  EXPECT_TRUE(DDT.pendingDeletedBB(BB2));
+  ASSERT_TRUE(isa<UnreachableInst>(BB2->getTerminator()));
+  EXPECT_EQ(BB2->getParent(), F);
+
+  // Queue up the DDT updates.
+  std::vector<DominatorTree::UpdateType> Updates;
+  Updates.reserve(4);
+  Updates.push_back({DominatorTree::Delete, BB0, BB2});
+  Updates.push_back({DominatorTree::Delete, BB2, BB3});
+
+  // Handle the specific shape case next.
+  // CFG Change: bb0 now only branches to bb3. We are preparing to remove bb1.
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 2u);
+  BB0->getTerminator()->eraseFromParent();
+  BranchInst::Create(BB3, BB0);
+  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 1u);
+
+  // Remove bb1 from F. This has to happen before the call to applyUpdates() for
+  // DDT to detect there is no longer an edge between bb1 -> bb3. The deleteBB()
+  // method converts bb1's TI into "unreachable".
+  ASSERT_FALSE(isa<UnreachableInst>(BB1->getTerminator()));
+  EXPECT_FALSE(DDT.pendingDeletedBB(BB1));
+  DDT.deleteBB(BB1);
+  EXPECT_TRUE(DDT.pendingDeletedBB(BB1));
+  ASSERT_TRUE(isa<UnreachableInst>(BB1->getTerminator()));
+  EXPECT_EQ(BB1->getParent(), F);
+
+  // Update the DDT. In this case we don't call DDT.insertEdge(BB0, BB3) because
+  // the edge previously existed at the start of this test when DT was first
+  // created.
+  Updates.push_back({DominatorTree::Delete, BB0, BB1});
+  Updates.push_back({DominatorTree::Delete, BB1, BB3});
+
+  // Verify everything.
+  DDT.applyUpdates(Updates);
+  ASSERT_TRUE(DDT.flush().verify());
+}




More information about the llvm-commits mailing list