[llvm] r336117 - Revert "[Dominators] Add the DomTreeUpdater class"

Jakub Kuderski via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 2 09:10:49 PDT 2018


Author: kuhar
Date: Mon Jul  2 09:10:49 2018
New Revision: 336117

URL: http://llvm.org/viewvc/llvm-project?rev=336117&view=rev
Log:
Revert "[Dominators] Add the DomTreeUpdater class"

Temporary revert because of a failing test on some buildbots.

This reverts commit r336114.

Removed:
    llvm/trunk/include/llvm/IR/DomTreeUpdater.h
    llvm/trunk/lib/IR/DomTreeUpdater.cpp
    llvm/trunk/unittests/IR/DomTreeUpdaterTest.cpp
Modified:
    llvm/trunk/include/llvm/module.modulemap
    llvm/trunk/lib/IR/CMakeLists.txt
    llvm/trunk/unittests/IR/CMakeLists.txt

Removed: llvm/trunk/include/llvm/IR/DomTreeUpdater.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DomTreeUpdater.h?rev=336116&view=auto
==============================================================================
--- llvm/trunk/include/llvm/IR/DomTreeUpdater.h (original)
+++ llvm/trunk/include/llvm/IR/DomTreeUpdater.h (removed)
@@ -1,242 +0,0 @@
-//===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the DomTreeUpdater class, which provides a uniform way to
-// update dominator tree related data structures.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DOMTREEUPDATER_H
-#define LLVM_DOMTREEUPDATER_H
-
-#include "llvm/Analysis/PostDominators.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/ValueHandle.h"
-#include "llvm/Support/GenericDomTree.h"
-#include <vector>
-
-namespace llvm {
-class DomTreeUpdater {
-public:
-  enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
-
-  explicit DomTreeUpdater(UpdateStrategy Strategy_) : Strategy(Strategy_) {}
-  DomTreeUpdater(DominatorTree &DT_, UpdateStrategy Strategy_)
-      : DT(&DT_), Strategy(Strategy_) {}
-  DomTreeUpdater(PostDominatorTree &PDT_, UpdateStrategy Strategy_)
-      : PDT(&PDT_), Strategy(Strategy_) {}
-  DomTreeUpdater(DominatorTree &DT_, PostDominatorTree &PDT_,
-                 UpdateStrategy Strategy_)
-      : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
-
-  ~DomTreeUpdater() { flush(); }
-
-  /// Returns the UpdateStrategy of the class instance.
-  UpdateStrategy getUpdateStrategy() const { return Strategy; };
-
-  /// Returns true if it holds a DominatorTree.
-  bool hasDomTree() const { return DT != nullptr; }
-
-  /// Returns true if it holds a PostDominatorTree.
-  bool hasPostDomTree() const { return PDT != nullptr; }
-
-  /// Returns true if there is BasicBlock awaiting deletion.
-  /// The deletion will only happen until a flush event and
-  /// all available trees are up-to-date.
-  /// Returns false under Eager UpdateStrategy.
-  bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); }
-
-  /// Returns true if DelBB is awaiting deletion.
-  /// Returns false under Eager UpdateStrategy.
-  bool isBBPendingDeletion(BasicBlock *DelBB) const;
-
-  /// Returns true if either of DT or PDT is valid and the tree has at
-  /// least one update pending. If DT or PDT is nullptr it is treated
-  /// as having no pending updates. This function does not check
-  /// whether there is BasicBlock awaiting deletion.
-  /// Returns false under Eager UpdateStrategy.
-  bool hasPendingUpdates() const;
-
-  /// Returns true if there are DominatorTree updates queued.
-  /// Returns false under Eager UpdateStrategy.
-  bool hasPendingDomTreeUpdates() const;
-
-  /// Returns true if there are PostDominatorTree updates queued.
-  /// Returns false under Eager UpdateStrategy.
-  bool hasPendingPostDomTreeUpdates() const;
-
-  /// Apply updates on all available trees. Under Eager UpdateStrategy with
-  /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will
-  /// discard duplicated updates and self-dominance updates. The Eager
-  /// Strategy applies the updates immediately while the Lazy Strategy
-  /// queues the updates. It is required for the state of
-  /// the LLVM IR to be updated *before* applying the Updates because the
-  /// internal update routine will analyze the current state of the relationship
-  /// between a pair of (From, To) BasicBlocks to determine whether a single
-  /// update needs to be discarded.
-  void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
-                    bool ForceRemoveDuplicates = false);
-
-  /// Notify all available trees on an edge insertion. Under either Strategy,
-  /// self-dominance update will be removed. The Eager Strategy applies
-  /// the update immediately while the Lazy Strategy queues the update.
-  /// It is recommended to only use this method when you have exactly one
-  /// insertion (and no deletions). It is recommended to use applyUpdates() in
-  /// all other cases. This function has to be called *after* making the update
-  /// on the actual CFG. An internal functions checks if the edge exists in the
-  /// CFG in DEBUG mode.
-  void insertEdge(BasicBlock *From, BasicBlock *To);
-
-  /// Notify all available trees on an edge insertion.
-  /// Under either Strategy, these updates will be discard silently in the
-  /// following sequence
-  /// 1. Invalid - Inserting an edge that does not exist in the CFG.
-  /// 2. Self-dominance update.
-  /// The Eager Strategy applies the update immediately while the Lazy Strategy
-  /// queues the update. It is recommended to only use this method when you have
-  /// exactly one insertion (and no deletions) and want to discard an invalid
-  /// update. Returns true if the update is valid.
-  bool insertEdgeRelaxed(BasicBlock *From, BasicBlock *To);
-
-  /// Notify all available trees on an edge deletion. Under either Strategy,
-  /// self-dominance update will be removed. The Eager Strategy applies
-  /// the update immediately while the Lazy Strategy queues the update.
-  /// It is recommended to only use this method when you have exactly one
-  /// deletion (and no insertions). It is recommended to use applyUpdates() in
-  /// all other cases. This function has to be called *after* making the update
-  /// on the actual CFG. An internal functions checks if the edge doesn't exist
-  /// in the CFG in DEBUG mode.
-  void deleteEdge(BasicBlock *From, BasicBlock *To);
-
-  /// Notify all available trees on an edge deletion.
-  /// Under either Strategy, these updates will be discard silently in the
-  /// following sequence:
-  /// 1. Invalid - Deleting an edge that still exists in the CFG.
-  /// 2. Self-dominance update.
-  /// The Eager Strategy applies the update immediately while the Lazy Strategy
-  /// queues the update. It is recommended to only use this method when you have
-  /// exactly one deletion (and no insertions) and want to discard an invalid
-  /// update. Returns true if the update is valid.
-  bool deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To);
-
-  /// Delete DelBB. DelBB will be removed from its Parent and
-  /// erased from available trees if it exists and finally get deleted.
-  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
-  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
-  /// all available trees are up-to-date.
-  void deleteBB(BasicBlock *DelBB);
-
-  /// Delete DelBB. DelBB will be removed from its Parent and
-  /// erased from available trees if it exists. Then the callback will
-  /// be called. Finally, DelBB will be deleted.
-  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
-  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
-  /// all available trees are up-to-date.
-  /// Multiple callbacks can be queued for one DelBB under Lazy UpdateStrategy.
-  void callbackDeleteBB(BasicBlock *DelBB,
-                        function_ref<void(BasicBlock *)> Callback);
-
-  /// Recalculate all available trees.
-  /// Under Lazy Strategy, available trees will only be recalculated if there
-  /// are pending updates or there is BasicBlock awaiting deletion. Returns true
-  /// if at least one tree is recalculated.
-  bool recalculate(Function &F);
-
-  /// Flush DomTree updates and return DomTree.
-  /// It also flush out of date updates applied by all available trees
-  /// and flush Deleted BBs if both trees are up-to-date.
-  /// It must only be called when it has a DomTree.
-  DominatorTree &getDomTree();
-
-  /// Flush PostDomTree updates and return PostDomTree.
-  /// It also flush out of date updates applied by all available trees
-  /// and flush Deleted BBs if both trees are up-to-date.
-  /// It must only be called when it has a PostDomTree.
-  PostDominatorTree &getPostDomTree();
-
-  /// Apply all pending updates to available trees and flush all BasicBlocks
-  /// awaiting deletion.
-  /// Does nothing under Eager UpdateStrategy.
-  void flush();
-
-  /// Debug method to help view the internal state of this class.
-  LLVM_DUMP_METHOD void dump() const;
-
-private:
-  class CallBackOnDeletion final : public CallbackVH {
-  public:
-    CallBackOnDeletion(BasicBlock *V, function_ref<void(BasicBlock *)> Callback)
-        : CallbackVH(V), DelBB(V), Callback_(Callback) {}
-
-  private:
-    BasicBlock *DelBB = nullptr;
-    function_ref<void(BasicBlock *)> Callback_;
-
-    void deleted() override {
-      Callback_(DelBB);
-      CallbackVH::deleted();
-    }
-  };
-
-  SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
-  size_t PendDTUpdateIndex = 0;
-  size_t PendPDTUpdateIndex = 0;
-  DominatorTree *DT = nullptr;
-  PostDominatorTree *PDT = nullptr;
-  const UpdateStrategy Strategy;
-  SmallPtrSet<BasicBlock *, 8> DeletedBBs;
-  std::vector<CallBackOnDeletion> Callbacks;
-  bool IsRecalculatingDomTree = false;
-  bool IsRecalculatingPostDomTree = false;
-
-  /// First remove all the instructions of DelBB and then make sure DelBB has a
-  /// valid terminator instruction which is necessary to have when DelBB still
-  /// has to be inside of its parent Function while awaiting deletion under Lazy
-  /// UpdateStrategy to prevent other routines from asserting the state of the
-  /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
-  void validateDeleteBB(BasicBlock *DelBB);
-
-  /// Returns true if at least one BasicBlock is deleted.
-  bool forceFlushDeletedBB();
-
-  /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy
-  /// UpdateStrategy. Returns true if the update is queued for update.
-  bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From,
-                       BasicBlock *To);
-
-  /// Helper function to apply all pending DomTree updates.
-  void applyDomTreeUpdates();
-
-  /// Helper function to apply all pending PostDomTree updates.
-  void applyPostDomTreeUpdates();
-
-  /// Helper function to flush deleted BasicBlocks if all available
-  /// trees are up-to-date.
-  void tryFlushDeletedBB();
-
-  /// Drop all updates applied by all available trees and delete BasicBlocks if
-  /// all available trees are up-to-date.
-  void dropOutOfDateUpdates();
-
-  /// Erase Basic Block node that has been unlinked from Function
-  /// in the DomTree and PostDomTree.
-  void eraseDelBBNode(BasicBlock *DelBB);
-
-  /// Returns true if the update appears in the LLVM IR.
-  /// It is used to check whether an update is valid in
-  /// insertEdge/deleteEdge or is unnecessary in the batch update.
-  bool isUpdateValid(DominatorTree::UpdateType Update) const;
-
-  /// Returns true if the update is self dominance.
-  bool isSelfDominance(DominatorTree::UpdateType Update) const;
-};
-} // namespace llvm
-
-#endif // LLVM_DOMTREEUPDATER_H

Modified: llvm/trunk/include/llvm/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/module.modulemap?rev=336117&r1=336116&r2=336117&view=diff
==============================================================================
--- llvm/trunk/include/llvm/module.modulemap (original)
+++ llvm/trunk/include/llvm/module.modulemap Mon Jul  2 09:10:49 2018
@@ -196,8 +196,6 @@ module LLVM_intrinsic_gen {
   module IR_CFG { header "IR/CFG.h" export * }
   module IR_ConstantRange { header "IR/ConstantRange.h" export * }
   module IR_Dominators { header "IR/Dominators.h" export * }
-  module Analysis_PostDominators { header "Analysis/PostDominators.h" export * }
-  module IR_DomTreeUpdater { header "IR/DomTreeUpdater.h" export * }
   module IR_IRBuilder { header "IR/IRBuilder.h" export * }
   module IR_PassManager { header "IR/PassManager.h" export * }
   module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * }

Modified: llvm/trunk/lib/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=336117&r1=336116&r2=336117&view=diff
==============================================================================
--- llvm/trunk/lib/IR/CMakeLists.txt (original)
+++ llvm/trunk/lib/IR/CMakeLists.txt Mon Jul  2 09:10:49 2018
@@ -21,7 +21,6 @@ add_llvm_library(LLVMCore
   DiagnosticInfo.cpp
   DiagnosticPrinter.cpp
   Dominators.cpp
-  DomTreeUpdater.cpp
   Function.cpp
   GVMaterializer.cpp
   Globals.cpp

Removed: llvm/trunk/lib/IR/DomTreeUpdater.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DomTreeUpdater.cpp?rev=336116&view=auto
==============================================================================
--- llvm/trunk/lib/IR/DomTreeUpdater.cpp (original)
+++ llvm/trunk/lib/IR/DomTreeUpdater.cpp (removed)
@@ -1,511 +0,0 @@
-//===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the DomTreeUpdater class, which provides a uniform way
-// to update dominator tree related data structures.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/IR/DomTreeUpdater.h"
-#include "llvm/Analysis/PostDominators.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/Support/GenericDomTree.h"
-#include <algorithm>
-
-namespace llvm {
-
-bool DomTreeUpdater::isUpdateValid(
-    const DominatorTree::UpdateType Update) const {
-  const auto *From = Update.getFrom();
-  const auto *To = Update.getTo();
-  const auto Kind = Update.getKind();
-
-  // Discard updates by inspecting the current state of successors of From.
-  // Since isUpdateValid() must be called *after* the Terminator of From is
-  // altered we can determine if the update is unnecessary for batch updates
-  // or invalid for a single update.
-  const bool HasEdge = llvm::any_of(
-      successors(From), [To](const BasicBlock *B) { return B == To; });
-
-  // If the IR does not match the update,
-  // 1. In batch updates, this update is unnecessary.
-  // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
-  // Edge does not exist in IR.
-  if (Kind == DominatorTree::Insert && !HasEdge)
-    return false;
-
-  // Edge exists in IR.
-  if (Kind == DominatorTree::Delete && HasEdge)
-    return false;
-
-  return true;
-}
-
-bool DomTreeUpdater::isSelfDominance(
-    const DominatorTree::UpdateType Update) const {
-  // Won't affect DomTree and PostDomTree.
-  return Update.getFrom() == Update.getTo();
-}
-
-bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
-                                     BasicBlock *From, BasicBlock *To) {
-  assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
-         "Call applyLazyUpdate() with Eager strategy error");
-  // Analyze pending updates to determine if the update is unnecessary.
-  const DominatorTree::UpdateType Update = {Kind, From, To};
-  const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
-                                                ? DominatorTree::Insert
-                                                : DominatorTree::Delete,
-                                            From, To};
-  // Only check duplicates in updates that are not applied by both trees.
-  auto I =
-      PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
-  const auto E = PendUpdates.end();
-
-  assert(I <= E && "Iterator out of range.");
-
-  for (; 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;
-}
-
-void DomTreeUpdater::applyDomTreeUpdates() {
-  // No pending DomTreeUpdates.
-  if (Strategy != UpdateStrategy::Lazy || !DT)
-    return;
-
-  // Only apply updates not are applied by DomTree.
-  if (hasPendingDomTreeUpdates()) {
-    const auto I = PendUpdates.begin() + PendDTUpdateIndex;
-    const auto E = PendUpdates.end();
-    assert(I < E && "Iterator range invalid; there should be DomTree updates.");
-    DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
-    PendDTUpdateIndex = PendUpdates.size();
-  }
-}
-
-void DomTreeUpdater::flush() {
-  applyDomTreeUpdates();
-  applyPostDomTreeUpdates();
-  dropOutOfDateUpdates();
-}
-
-void DomTreeUpdater::applyPostDomTreeUpdates() {
-  // No pending PostDomTreeUpdates.
-  if (Strategy != UpdateStrategy::Lazy || !PDT)
-    return;
-
-  // Only apply updates not are applied by PostDomTree.
-  if (hasPendingPostDomTreeUpdates()) {
-    const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
-    const auto E = PendUpdates.end();
-    assert(I < E &&
-           "Iterator range invalid; there should be PostDomTree updates.");
-    PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
-    PendPDTUpdateIndex = PendUpdates.size();
-  }
-}
-
-void DomTreeUpdater::tryFlushDeletedBB() {
-  if (!hasPendingUpdates())
-    forceFlushDeletedBB();
-}
-
-bool DomTreeUpdater::forceFlushDeletedBB() {
-  if (DeletedBBs.empty())
-    return false;
-
-  for (auto *BB : DeletedBBs) {
-    BB->removeFromParent();
-    eraseDelBBNode(BB);
-    delete BB;
-  }
-  DeletedBBs.clear();
-  Callbacks.clear();
-  return true;
-}
-
-bool DomTreeUpdater::recalculate(Function &F) {
-  if (!DT && !PDT)
-    return false;
-
-  if (Strategy == UpdateStrategy::Eager) {
-    if (DT)
-      DT->recalculate(F);
-    if (PDT)
-      PDT->recalculate(F);
-    return true;
-  }
-
-  // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
-  IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
-
-  // Because all trees are going to be up-to-date after recalculation,
-  // flush awaiting deleted BasicBlocks.
-  if (forceFlushDeletedBB() || hasPendingUpdates()) {
-    if (DT)
-      DT->recalculate(F);
-    if (PDT)
-      PDT->recalculate(F);
-
-    // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
-    IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
-    PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
-    dropOutOfDateUpdates();
-    return true;
-  }
-
-  // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
-  IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
-  return false;
-}
-
-bool DomTreeUpdater::hasPendingUpdates() const {
-  return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
-}
-
-bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
-  if (!DT)
-    return false;
-  return PendUpdates.size() != PendDTUpdateIndex;
-}
-
-bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
-  if (!PDT)
-    return false;
-  return PendUpdates.size() != PendPDTUpdateIndex;
-}
-
-bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
-  if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
-    return false;
-  return DeletedBBs.count(DelBB) != 0;
-}
-
-// The DT and PDT require the nodes related to updates
-// are not deleted when update functions are called.
-// So BasicBlock deletions must be pended when the
-// UpdateStrategy is Lazy. When the UpdateStrategy is
-// Eager, the BasicBlock will be deleted immediately.
-void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
-  validateDeleteBB(DelBB);
-  if (Strategy == UpdateStrategy::Lazy) {
-    DeletedBBs.insert(DelBB);
-    return;
-  }
-
-  DelBB->removeFromParent();
-  eraseDelBBNode(DelBB);
-  delete DelBB;
-}
-
-void DomTreeUpdater::callbackDeleteBB(
-    BasicBlock *DelBB, function_ref<void(BasicBlock *)> Callback) {
-  validateDeleteBB(DelBB);
-  if (Strategy == UpdateStrategy::Lazy) {
-    Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
-    DeletedBBs.insert(DelBB);
-    return;
-  }
-
-  DelBB->removeFromParent();
-  eraseDelBBNode(DelBB);
-  Callback(DelBB);
-  delete DelBB;
-}
-
-void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
-  if (DT && !IsRecalculatingDomTree)
-    if (DT->getNode(DelBB))
-      DT->eraseNode(DelBB);
-
-  if (PDT && !IsRecalculatingPostDomTree)
-    if (PDT->getNode(DelBB))
-      PDT->eraseNode(DelBB);
-}
-
-void DomTreeUpdater::validateDeleteBB(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);
-}
-
-void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
-                                  bool ForceRemoveDuplicates) {
-  if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
-    SmallVector<DominatorTree::UpdateType, 8> Seen;
-    for (const auto U : Updates)
-      // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
-      // on analysis.
-      if (llvm::none_of(
-              Seen,
-              [U](const DominatorTree::UpdateType S) { return S == U; }) &&
-          isUpdateValid(U) && !isSelfDominance(U)) {
-        Seen.push_back(U);
-        if (Strategy == UpdateStrategy::Lazy)
-          applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
-      }
-    if (Strategy == UpdateStrategy::Lazy)
-      return;
-
-    if (DT)
-      DT->applyUpdates(Seen);
-    if (PDT)
-      PDT->applyUpdates(Seen);
-    return;
-  }
-
-  if (DT)
-    DT->applyUpdates(Updates);
-  if (PDT)
-    PDT->applyUpdates(Updates);
-}
-
-DominatorTree &DomTreeUpdater::getDomTree() {
-  assert(DT && "Invalid acquisition of a null DomTree");
-  applyDomTreeUpdates();
-  dropOutOfDateUpdates();
-  return *DT;
-}
-
-PostDominatorTree &DomTreeUpdater::getPostDomTree() {
-  assert(PDT && "Invalid acquisition of a null PostDomTree");
-  applyPostDomTreeUpdates();
-  dropOutOfDateUpdates();
-  return *PDT;
-}
-
-void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) {
-
-#ifndef NDEBUG
-  assert(isUpdateValid({DominatorTree::Insert, From, To}) &&
-         "Inserted edge does not appear in the CFG");
-#endif
-
-  // Won't affect DomTree and PostDomTree; discard update.
-  if (From == To)
-    return;
-
-  if (Strategy == UpdateStrategy::Eager) {
-    if (DT)
-      DT->insertEdge(From, To);
-    if (PDT)
-      PDT->insertEdge(From, To);
-    return;
-  }
-
-  applyLazyUpdate(DominatorTree::Insert, From, To);
-}
-
-bool DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
-  if (!isUpdateValid({DominatorTree::Insert, From, To}))
-    return false;
-
-  if (From == To)
-    return true;
-
-  if (Strategy == UpdateStrategy::Eager) {
-    if (DT)
-      DT->insertEdge(From, To);
-    if (PDT)
-      PDT->insertEdge(From, To);
-    return true;
-  }
-
-  applyLazyUpdate(DominatorTree::Insert, From, To);
-  return true;
-}
-
-void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
-
-#ifndef NDEBUG
-  assert(isUpdateValid({DominatorTree::Delete, From, To}) &&
-         "Deleted edge still exists in the CFG!");
-#endif
-
-  // Won't affect DomTree and PostDomTree; discard update.
-  if (From == To)
-    return;
-
-  if (Strategy == UpdateStrategy::Eager) {
-    if (DT)
-      DT->deleteEdge(From, To);
-    if (PDT)
-      PDT->deleteEdge(From, To);
-    return;
-  }
-
-  applyLazyUpdate(DominatorTree::Delete, From, To);
-}
-
-bool DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
-  if (!isUpdateValid({DominatorTree::Delete, From, To}))
-    return false;
-
-  if (From == To)
-    return true;
-
-  if (Strategy == UpdateStrategy::Eager) {
-    if (DT)
-      DT->deleteEdge(From, To);
-    if (PDT)
-      PDT->deleteEdge(From, To);
-    return true;
-  }
-
-  applyLazyUpdate(DominatorTree::Delete, From, To);
-  return true;
-}
-
-void DomTreeUpdater::dropOutOfDateUpdates() {
-  if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
-    return;
-
-  tryFlushDeletedBB();
-
-  // Drop all updates applied by both trees.
-  if (!DT)
-    PendDTUpdateIndex = PendUpdates.size();
-  if (!PDT)
-    PendPDTUpdateIndex = PendUpdates.size();
-
-  const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
-  const auto B = PendUpdates.begin();
-  const auto E = PendUpdates.begin() + dropIndex;
-  assert(B <= E && "Iterator out of range.");
-  PendUpdates.erase(B, E);
-  // Calculate current index.
-  PendDTUpdateIndex -= dropIndex;
-  PendPDTUpdateIndex -= dropIndex;
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
-  raw_ostream &OS = llvm::dbgs();
-
-  OS << "Available Trees: ";
-  if (DT || PDT) {
-    if (DT)
-      OS << "DomTree ";
-    if (PDT)
-      OS << "PostDomTree ";
-    OS << "\n";
-  } else
-    OS << "None\n";
-
-  OS << "UpdateStrategy: ";
-  if (Strategy == UpdateStrategy::Eager) {
-    OS << "Eager\n";
-    return;
-  } else
-    OS << "Lazy\n";
-  int Index = 0;
-
-  auto printUpdates =
-      [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
-          ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
-        if (begin == end)
-          OS << "  None\n";
-        Index = 0;
-        for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
-          auto U = *It;
-          OS << "  " << Index << " : ";
-          ++Index;
-          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";
-          }
-        }
-      };
-
-  if (DT) {
-    const auto I = PendUpdates.begin() + PendDTUpdateIndex;
-    assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
-           "Iterator out of range.");
-    OS << "Applied but not cleared DomTreeUpdates:\n";
-    printUpdates(PendUpdates.begin(), I);
-    OS << "Pending DomTreeUpdates:\n";
-    printUpdates(I, PendUpdates.end());
-  }
-
-  if (PDT) {
-    const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
-    assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
-           "Iterator out of range.");
-    OS << "Applied but not cleared PostDomTreeUpdates:\n";
-    printUpdates(PendUpdates.begin(), I);
-    OS << "Pending PostDomTreeUpdates:\n";
-    printUpdates(I, PendUpdates.end());
-  }
-
-  OS << "Pending DeletedBBs:\n";
-  Index = 0;
-  for (auto BB : DeletedBBs) {
-    OS << "  " << Index << " : ";
-    ++Index;
-    if (BB->hasName())
-      OS << BB->getName() << "(";
-    else
-      OS << "(no_name)(";
-    OS << BB << ")\n";
-  }
-
-  OS << "Pending Callbacks:\n";
-  Index = 0;
-  for (auto BB : Callbacks) {
-    OS << "  " << Index << " : ";
-    ++Index;
-    if (BB->hasName())
-      OS << BB->getName() << "(";
-    else
-      OS << "(no_name)(";
-    OS << BB << ")\n";
-  }
-}
-#endif
-} // namespace llvm

Modified: llvm/trunk/unittests/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=336117&r1=336116&r2=336117&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/CMakeLists.txt (original)
+++ llvm/trunk/unittests/IR/CMakeLists.txt Mon Jul  2 09:10:49 2018
@@ -18,7 +18,6 @@ add_llvm_unittest(IRTests
   DeferredDominanceTest.cpp
   DominatorTreeTest.cpp
   DominatorTreeBatchUpdatesTest.cpp
-  DomTreeUpdaterTest.cpp
   FunctionTest.cpp
   PassBuilderCallbacksTest.cpp
   IRBuilderTest.cpp

Removed: llvm/trunk/unittests/IR/DomTreeUpdaterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/DomTreeUpdaterTest.cpp?rev=336116&view=auto
==============================================================================
--- llvm/trunk/unittests/IR/DomTreeUpdaterTest.cpp (original)
+++ llvm/trunk/unittests/IR/DomTreeUpdaterTest.cpp (removed)
@@ -1,693 +0,0 @@
-//==- llvm/unittests/IR/DomTreeUpdaterTest.cpp - DomTreeUpdater 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/IR/DomTreeUpdater.h"
-#include "llvm/Analysis/PostDominators.h"
-#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"
-#include <algorithm>
-
-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(DomTreeUpdater, EagerUpdateBasicOperations) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                          define i32 @f(i32 %i, i32 *%p) {
-                          bb0:
-                             store i32 %i, i32 *%p
-                             switch i32 %i, label %bb1 [
-                               i32 1, label %bb2
-                               i32 2, label %bb3
-                             ]
-                          bb1:
-                             ret i32 1
-                          bb2:
-                             ret i32 2
-                          bb3:
-                             ret i32 3
-                          })";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DomTreeUpdater.
-  DominatorTree DT(*F);
-  PostDominatorTree PDT(*F);
-  DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
-
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_TRUE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.getPostDomTree().verify());
-  ASSERT_FALSE(DTU.hasPendingUpdates());
-
-  Function::iterator FI = F->begin();
-  BasicBlock *BB0 = &*FI++;
-  BasicBlock *BB1 = &*FI++;
-  BasicBlock *BB2 = &*FI++;
-  BasicBlock *BB3 = &*FI++;
-  SwitchInst *SI = dyn_cast<SwitchInst>(BB0->getTerminator());
-  ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
-
-  ASSERT_FALSE(DTU.insertEdgeRelaxed(BB0, BB0));
-  ASSERT_TRUE(DTU.deleteEdgeRelaxed(BB0, BB0));
-
-  // 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});
-
-  // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
-  Updates.push_back({DominatorTree::Insert, BB1, BB2});
-  // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
-  Updates.push_back({DominatorTree::Delete, BB0, BB1});
-
-  // CFG Change: remove edge bb0 -> bb3.
-  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 3u);
-  BB3->removePredecessor(BB0);
-  for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
-    if (i->getCaseSuccessor() == BB3) {
-      SI->removeCase(i);
-      break;
-    }
-  }
-  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.
-  ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
-  DTU.applyUpdates(Updates, /*ForceRemoveDuplicates*/ true);
-  ASSERT_FALSE(DTU.hasPendingUpdates());
-
-  // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
-  ASSERT_FALSE(DTU.insertEdgeRelaxed(BB1, BB2));
-  // Invalid Delete: edge exists bb0 -> bb1 after change to bb0.
-  ASSERT_FALSE(DTU.deleteEdgeRelaxed(BB0, BB1));
-
-  // DTU working with Eager UpdateStrategy does not need to flush.
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-
-  // Test callback utils.
-  ASSERT_EQ(BB3->getParent(), F);
-  DTU.callbackDeleteBB(BB3,
-                       [&F](BasicBlock *BB) { ASSERT_NE(BB->getParent(), F); });
-
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-  ASSERT_FALSE(DTU.hasPendingUpdates());
-
-  // Unnecessary flush() test
-  DTU.flush();
-  EXPECT_TRUE(DT.verify());
-  EXPECT_TRUE(PDT.verify());
-
-  // Remove all case branch to BB2 to test Eager recalculation.
-  // Code section from llvm::ConstantFoldTerminator
-  for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
-    if (i->getCaseSuccessor() == BB2) {
-      // Remove this entry.
-      BB2->removePredecessor(BB0);
-      i = SI->removeCase(i);
-      e = SI->case_end();
-    } else
-      ++i;
-  }
-  ASSERT_FALSE(DT.verify());
-  ASSERT_FALSE(PDT.verify());
-  DTU.recalculate(*F);
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-}
-
-TEST(DomTreeUpdater, EagerUpdateReplaceEntryBB) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f() {
-                           bb0:
-                              br label %bb1
-                            bb1:
-                              ret i32 1
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DTU.
-  DominatorTree DT(*F);
-  PostDominatorTree PDT(*F);
-  DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Eager);
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_TRUE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Eager);
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.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);
-
-  ASSERT_TRUE(DTU.insertEdgeRelaxed(NewEntry, BB0));
-
-  // Changing the Entry BB requires a full recalculation of DomTree.
-  DTU.recalculate(*F);
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.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 DTU. At this point bb0 now has no predecessors but is still a
-  // Child of F.
-  DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
-                    {DominatorTree::Insert, NewEntry, BB1}});
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-
-  // Now remove bb0 from F.
-  ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
-  DTU.deleteBB(BB0);
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-}
-
-TEST(DomTreeUpdater, LazyUpdateDTBasicOperations) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f(i32 %i, i32 *%p) {
-                            bb0:
-                              store i32 %i, i32 *%p
-                              switch i32 %i, label %bb1 [
-                                i32 0, label %bb2
-                                i32 1, label %bb2
-                                i32 2, label %bb3
-                              ]
-                            bb1:
-                              ret i32 1
-                            bb2:
-                              ret i32 2
-                            bb3:
-                              ret i32 3
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DTU.
-  DominatorTree DT(*F);
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_FALSE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-
-  Function::iterator FI = F->begin();
-  BasicBlock *BB0 = &*FI++;
-  BasicBlock *BB1 = &*FI++;
-  BasicBlock *BB2 = &*FI++;
-  BasicBlock *BB3 = &*FI++;
-
-  // Test discards of self-domination update.
-  DTU.deleteEdge(BB0, BB0);
-  ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
-
-  // 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});
-
-  // Invalid Insert: no edge bb1 -> bb2 after change to bb0.
-  Updates.push_back({DominatorTree::Insert, BB1, BB2});
-  // Invalid 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);
-
-  // Verify. Updates to DTU must be applied *after* all changes to the CFG
-  // (including block deletion).
-  DTU.applyUpdates(Updates);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-
-  // 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 all the pending updates
-  // are applied to all trees held by the DomTreeUpdater (DomTree/PostDomTree).
-  // 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 DominatorTrees. This code will crash if it is placed before
-  // the BranchInst::Create() call above. After a deletion of a BasicBlock. Only
-  // an explicit flush event can trigger the flushing of deleteBBs. Because some
-  // passes using Lazy UpdateStrategy rely on this behavior.
-
-  ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
-  EXPECT_FALSE(DTU.hasPendingDeletedBB());
-  DTU.deleteBB(BB3);
-  EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
-  EXPECT_TRUE(DTU.hasPendingDeletedBB());
-  ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_EQ(BB3->getParent(), F);
-  DTU.recalculate(*F);
-
-  EXPECT_FALSE(DTU.hasPendingDeletedBB());
-}
-
-TEST(DomTreeUpdater, LazyUpdateDTInheritedPreds) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f(i32 %i, i32 *%p) {
-                            bb0:
-                              store i32 %i, i32 *%p
-                              switch i32 %i, label %bb1 [
-                                i32 2, label %bb2
-                                i32 3, label %bb3
-                              ]
-                            bb1:
-                              br label %bb3
-                            bb2:
-                              br label %bb3
-                            bb3:
-                              ret i32 3
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DTU.
-  DominatorTree DT(*F);
-  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_FALSE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.getDomTree().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
-  // DTU are not. In the first case we must have DTU.insertEdge(Pred1, Succ)
-  // while in the latter case we must *NOT* have DTU.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);
-
-  // Test callback utils.
-  std::vector<BasicBlock *> BasicBlocks;
-  BasicBlocks.push_back(BB1);
-  BasicBlocks.push_back(BB2);
-  auto Eraser = [&](BasicBlock *BB) {
-    BasicBlocks.erase(
-        std::remove_if(BasicBlocks.begin(), BasicBlocks.end(),
-                       [&](const BasicBlock *i) { return i == BB; }),
-        BasicBlocks.end());
-  };
-  ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
-  // Remove bb2 from F. This has to happen before the call to applyUpdates() for
-  // DTU 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(DTU.isBBPendingDeletion(BB2));
-  DTU.callbackDeleteBB(BB2, Eraser);
-  EXPECT_TRUE(DTU.isBBPendingDeletion(BB2));
-  ASSERT_TRUE(isa<UnreachableInst>(BB2->getTerminator()));
-  EXPECT_EQ(BB2->getParent(), F);
-
-  // Queue up the DTU 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
-  // DTU 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(DTU.isBBPendingDeletion(BB1));
-  DTU.callbackDeleteBB(BB1, Eraser);
-  EXPECT_TRUE(DTU.isBBPendingDeletion(BB1));
-  ASSERT_TRUE(isa<UnreachableInst>(BB1->getTerminator()));
-  EXPECT_EQ(BB1->getParent(), F);
-
-  // Update the DTU. In this case we don't call DTU.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.
-  DTU.applyUpdates(Updates);
-  ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(2));
-  DTU.flush();
-  ASSERT_EQ(BasicBlocks.size(), static_cast<size_t>(0));
-  ASSERT_TRUE(DT.verify());
-}
-
-TEST(DomTreeUpdater, LazyUpdateBasicOperations) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f(i32 %i, i32 *%p) {
-                            bb0:
-                              store i32 %i, i32 *%p
-                              switch i32 %i, label %bb1 [
-                                i32 0, label %bb2
-                                i32 1, label %bb2
-                                i32 2, label %bb3
-                              ]
-                            bb1:
-                              ret i32 1
-                            bb2:
-                              ret i32 2
-                            bb3:
-                              ret i32 3
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DTU.
-  DominatorTree DT(*F);
-  PostDominatorTree PDT(*F);
-  DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_TRUE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.getPostDomTree().verify());
-
-  Function::iterator FI = F->begin();
-  BasicBlock *BB0 = &*FI++;
-  BasicBlock *BB1 = &*FI++;
-  BasicBlock *BB2 = &*FI++;
-  BasicBlock *BB3 = &*FI++;
-  // Test discards of self-domination update.
-  DTU.deleteEdge(BB0, BB0);
-
-  // 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 DTU.flushDomTree 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.
-  bool CallbackFlag = false;
-  ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
-  DTU.callbackDeleteBB(BB3, [&](BasicBlock *) { CallbackFlag = true; });
-  EXPECT_TRUE(DTU.isBBPendingDeletion(BB3));
-  ASSERT_TRUE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_EQ(BB3->getParent(), F);
-
-  // Verify. Updates to DTU must be applied *after* all changes to the CFG
-  // (including block deletion).
-  DTU.applyUpdates(Updates);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.hasPendingUpdates());
-  ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
-  ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
-  ASSERT_TRUE(DTU.hasPendingDeletedBB());
-  ASSERT_TRUE(DTU.getPostDomTree().verify());
-  ASSERT_FALSE(DTU.hasPendingUpdates());
-  ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
-  ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
-  ASSERT_FALSE(DTU.hasPendingDeletedBB());
-  ASSERT_EQ(CallbackFlag, true);
-}
-
-TEST(DomTreeUpdater, LazyUpdateReplaceEntryBB) {
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f() {
-                           bb0:
-                              br label %bb1
-                            bb1:
-                              ret i32 1
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DTU.
-  DominatorTree DT(*F);
-  PostDominatorTree PDT(*F);
-  DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_TRUE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.getPostDomTree().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_entry -> bb0. Without this the
-  // recalculate() call below will not actually recalculate the DT as there
-  // are no changes pending and no blocks deleted.
-  DTU.insertEdge(NewEntry, BB0);
-
-  // Changing the Entry BB requires a full recalculation.
-  DTU.recalculate(*F);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.getPostDomTree().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 DTU. At this point bb0 now has no predecessors but is still a
-  // Child of F.
-  DTU.applyUpdates({{DominatorTree::Delete, NewEntry, BB0},
-                    {DominatorTree::Insert, NewEntry, BB1}});
-  DTU.flush();
-  ASSERT_TRUE(DT.verify());
-  ASSERT_TRUE(PDT.verify());
-
-  // Now remove bb0 from F.
-  ASSERT_FALSE(isa<UnreachableInst>(BB0->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB0));
-  DTU.deleteBB(BB0);
-  EXPECT_TRUE(DTU.isBBPendingDeletion(BB0));
-  ASSERT_TRUE(isa<UnreachableInst>(BB0->getTerminator()));
-  EXPECT_EQ(BB0->getParent(), F);
-
-  // Perform a full recalculation of the DTU. 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.
-  ASSERT_TRUE(DTU.hasPendingDeletedBB());
-  DTU.recalculate(*F);
-  ASSERT_FALSE(DTU.hasPendingDeletedBB());
-}
-
-TEST(DomTreeUpdater, LazyUpdateStepTest) {
-  // This test focus on testing a DTU holding both trees applying multiple
-  // updates and DT/PDT not flushed together.
-  StringRef FuncName = "f";
-  StringRef ModuleString = R"(
-                           define i32 @f(i32 %i, i32 *%p) {
-                            bb0:
-                              store i32 %i, i32 *%p
-                              switch i32 %i, label %bb1 [
-                                i32 0, label %bb1
-                                i32 1, label %bb2
-                                i32 2, label %bb3
-                                i32 3, label %bb1
-                              ]
-                            bb1:
-                              ret i32 1
-                            bb2:
-                              ret i32 2
-                            bb3:
-                              ret i32 3
-                           }
-                           )";
-  // Make the module.
-  LLVMContext Context;
-  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
-  Function *F = M->getFunction(FuncName);
-
-  // Make the DomTreeUpdater.
-  DominatorTree DT(*F);
-  PostDominatorTree PDT(*F);
-  DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
-
-  ASSERT_TRUE(DTU.hasDomTree());
-  ASSERT_TRUE(DTU.hasPostDomTree());
-  ASSERT_EQ(DTU.getUpdateStrategy(), DomTreeUpdater::UpdateStrategy::Lazy);
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.getPostDomTree().verify());
-  ASSERT_FALSE(DTU.hasPendingUpdates());
-
-  Function::iterator FI = F->begin();
-  BasicBlock *BB0 = &*FI++;
-  FI++;
-  BasicBlock *BB2 = &*FI++;
-  BasicBlock *BB3 = &*FI++;
-  SwitchInst *SI = dyn_cast<SwitchInst>(BB0->getTerminator());
-  ASSERT_NE(SI, nullptr) << "Couldn't get SwitchInst.";
-
-  // Delete edge bb0 -> bb3 and push the update twice to verify duplicate
-  // entries are discarded.
-  std::vector<DominatorTree::UpdateType> Updates;
-  Updates.reserve(1);
-  Updates.push_back({DominatorTree::Delete, BB0, BB3});
-
-  // CFG Change: remove edge bb0 -> bb3.
-  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 5u);
-  BB3->removePredecessor(BB0);
-  for (auto i = SI->case_begin(), e = SI->case_end(); i != e; ++i) {
-    if (i->getCaseIndex() == 2) {
-      SI->removeCase(i);
-      break;
-    }
-  }
-  EXPECT_EQ(BB0->getTerminator()->getNumSuccessors(), 4u);
-  // 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.
-  ASSERT_FALSE(isa<UnreachableInst>(BB3->getTerminator()));
-  EXPECT_FALSE(DTU.isBBPendingDeletion(BB3));
-  DTU.applyUpdates(Updates);
-
-  // Only flush DomTree.
-  ASSERT_TRUE(DTU.getDomTree().verify());
-  ASSERT_TRUE(DTU.hasPendingPostDomTreeUpdates());
-  ASSERT_FALSE(DTU.hasPendingDomTreeUpdates());
-
-  ASSERT_EQ(BB3->getParent(), F);
-  DTU.deleteBB(BB3);
-
-  Updates.clear();
-
-  // Remove all case branch to BB2 to test Eager recalculation.
-  // Code section from llvm::ConstantFoldTerminator
-  for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
-    if (i->getCaseSuccessor() == BB2) {
-      // Remove this entry.
-      BB2->removePredecessor(BB0);
-      i = SI->removeCase(i);
-      e = SI->case_end();
-      Updates.push_back({DominatorTree::Delete, BB0, BB2});
-    } else
-      ++i;
-  }
-
-  DTU.applyUpdates(Updates);
-  // flush PostDomTree
-  ASSERT_TRUE(DTU.getPostDomTree().verify());
-  ASSERT_FALSE(DTU.hasPendingPostDomTreeUpdates());
-  ASSERT_TRUE(DTU.hasPendingDomTreeUpdates());
-  // flush both trees
-  DTU.flush();
-  ASSERT_TRUE(DT.verify());
-}




More information about the llvm-commits mailing list