[llvm] [DomTreeUpdater] Split implementations (PR #97027)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 28 03:08:38 PDT 2024


https://github.com/paperchalice updated https://github.com/llvm/llvm-project/pull/97027

>From e6393eeb145f8310dfc1e5fae0e712235273dc30 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Fri, 28 Jun 2024 17:25:12 +0800
Subject: [PATCH 1/2] [DomTreeUpdater] Split implementations Move
 implementations of `GenericDomTreeUpdater` to GenericDomTreeUpdaterImpl.h

---
 llvm/include/llvm/Analysis/DomTreeUpdater.h   |  25 +-
 .../llvm/Analysis/GenericDomTreeUpdater.h     | 377 ++------------
 .../llvm/Analysis/GenericDomTreeUpdaterImpl.h | 477 ++++++++++++++++++
 .../llvm/CodeGen/MachineDomTreeUpdater.h      |  14 +-
 llvm/lib/Analysis/DomTreeUpdater.cpp          |  24 +
 llvm/lib/CodeGen/MachineDomTreeUpdater.cpp    |   8 +-
 6 files changed, 555 insertions(+), 370 deletions(-)
 create mode 100644 llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h

diff --git a/llvm/include/llvm/Analysis/DomTreeUpdater.h b/llvm/include/llvm/Analysis/DomTreeUpdater.h
index 2b838a311440e..9ffd4948c1750 100644
--- a/llvm/include/llvm/Analysis/DomTreeUpdater.h
+++ b/llvm/include/llvm/Analysis/DomTreeUpdater.h
@@ -16,7 +16,6 @@
 
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Analysis/GenericDomTreeUpdater.h"
-#include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Support/Compiler.h"
@@ -26,6 +25,8 @@
 
 namespace llvm {
 
+class PostDominatorTree;
+
 class DomTreeUpdater
     : public GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
                                    PostDominatorTree> {
@@ -110,27 +111,15 @@ class DomTreeUpdater
   bool forceFlushDeletedBB();
 
   /// Debug method to help view the internal state of this class.
-  LLVM_DUMP_METHOD void dump() const {
-    Base::dump();
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-    raw_ostream &OS = dbgs();
-    OS << "Pending Callbacks:\n";
-    int Index = 0;
-    for (const auto &BB : Callbacks) {
-      OS << "  " << Index << " : ";
-      ++Index;
-      if (BB->hasName())
-        OS << BB->getName() << "(";
-      else
-        OS << "(no_name)(";
-      OS << BB << ")\n";
-    }
-#endif
-  }
+  LLVM_DUMP_METHOD void dump() const;
 };
 
 extern template class GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
                                             PostDominatorTree>;
+
+extern template void
+GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
+                      PostDominatorTree>::recalculate(Function &F);
 } // namespace llvm
 
 #endif // LLVM_ANALYSIS_DOMTREEUPDATER_H
diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
index 7092c67083a67..1a86398e4fc68 100644
--- a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
@@ -16,91 +16,67 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallSet.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Compiler.h"
 
 namespace llvm {
 
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 class GenericDomTreeUpdater {
-  DerivedT &derived() { return *static_cast<DerivedT *>(this); }
-  const DerivedT &derived() const {
-    return *static_cast<const DerivedT *>(this);
-  }
+  DerivedT &derived();
+  const DerivedT &derived() const;
 
 public:
   enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
   using BasicBlockT = typename DomTreeT::NodeType;
 
-  explicit GenericDomTreeUpdater(UpdateStrategy Strategy_)
-      : Strategy(Strategy_) {}
-  GenericDomTreeUpdater(DomTreeT &DT_, UpdateStrategy Strategy_)
-      : DT(&DT_), Strategy(Strategy_) {}
-  GenericDomTreeUpdater(DomTreeT *DT_, UpdateStrategy Strategy_)
-      : DT(DT_), Strategy(Strategy_) {}
-  GenericDomTreeUpdater(PostDomTreeT &PDT_, UpdateStrategy Strategy_)
-      : PDT(&PDT_), Strategy(Strategy_) {}
-  GenericDomTreeUpdater(PostDomTreeT *PDT_, UpdateStrategy Strategy_)
-      : PDT(PDT_), Strategy(Strategy_) {}
+  explicit GenericDomTreeUpdater(UpdateStrategy Strategy_);
+  GenericDomTreeUpdater(DomTreeT &DT_, UpdateStrategy Strategy_);
+  GenericDomTreeUpdater(DomTreeT *DT_, UpdateStrategy Strategy_);
+  GenericDomTreeUpdater(PostDomTreeT &PDT_, UpdateStrategy Strategy_);
+  GenericDomTreeUpdater(PostDomTreeT *PDT_, UpdateStrategy Strategy_);
   GenericDomTreeUpdater(DomTreeT &DT_, PostDomTreeT &PDT_,
-                        UpdateStrategy Strategy_)
-      : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
+                        UpdateStrategy Strategy_);
   GenericDomTreeUpdater(DomTreeT *DT_, PostDomTreeT *PDT_,
-                        UpdateStrategy Strategy_)
-      : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
+                        UpdateStrategy Strategy_);
 
-  ~GenericDomTreeUpdater() { flush(); }
+  ~GenericDomTreeUpdater();
 
   /// Returns true if the current strategy is Lazy.
-  bool isLazy() const { return Strategy == UpdateStrategy::Lazy; };
+  bool isLazy() const;
 
   /// Returns true if the current strategy is Eager.
-  bool isEager() const { return Strategy == UpdateStrategy::Eager; };
+  bool isEager() const;
 
   /// Returns true if it holds a DomTreeT.
-  bool hasDomTree() const { return DT != nullptr; }
+  bool hasDomTree() const;
 
   /// Returns true if it holds a PostDomTreeT.
-  bool hasPostDomTree() const { return PDT != nullptr; }
+  bool hasPostDomTree() const;
 
   /// Returns true if there is BasicBlockT 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(); }
+  bool hasPendingDeletedBB() const;
 
   /// Returns true if DelBB is awaiting deletion.
   /// Returns false under Eager UpdateStrategy.
-  bool isBBPendingDeletion(BasicBlockT *DelBB) const {
-    if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
-      return false;
-    return DeletedBBs.contains(DelBB);
-  }
+  bool isBBPendingDeletion(BasicBlockT *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 MachineBasicBlock awaiting deletion.
   /// Returns false under Eager UpdateStrategy.
-  bool hasPendingUpdates() const {
-    return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
-  }
+  bool hasPendingUpdates() const;
 
   /// Returns true if there are DomTreeT updates queued.
   /// Returns false under Eager UpdateStrategy or DT is nullptr.
-  bool hasPendingDomTreeUpdates() const {
-    if (!DT)
-      return false;
-    return PendUpdates.size() != PendDTUpdateIndex;
-  }
+  bool hasPendingDomTreeUpdates() const;
 
   /// Returns true if there are PostDomTreeT updates queued.
   /// Returns false under Eager UpdateStrategy or PDT is nullptr.
-  bool hasPendingPostDomTreeUpdates() const {
-    if (!PDT)
-      return false;
-    return PendUpdates.size() != PendPDTUpdateIndex;
-  }
+  bool hasPendingPostDomTreeUpdates() const;
 
   ///@{
   /// \name Mutation APIs
@@ -126,34 +102,7 @@ class GenericDomTreeUpdater {
   /// Notify DTU that the entry block was replaced.
   /// Recalculate all available trees and flush all BasicBlocks
   /// awaiting deletion immediately.
-  template <typename FuncT> void recalculate(FuncT &F) {
-    if (Strategy == UpdateStrategy::Eager) {
-      if (DT)
-        DT->recalculate(F);
-      if (PDT)
-        PDT->recalculate(F);
-      return;
-    }
-
-    // There is little performance gain if we pend the recalculation under
-    // Lazy UpdateStrategy so we recalculate available trees immediately.
-
-    // 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.
-    derived().forceFlushDeletedBB();
-    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();
-  }
+  template <typename FuncT> void recalculate(FuncT &F);
 
   /// Submit updates to all available trees.
   /// The Eager Strategy flushes updates immediately while the Lazy Strategy
@@ -170,24 +119,7 @@ class GenericDomTreeUpdater {
   /// 2. It is illegal to submit any update that has already been submitted,
   /// i.e., you are supposed not to insert an existent edge or delete a
   /// nonexistent edge.
-  void applyUpdates(ArrayRef<typename DomTreeT::UpdateType> Updates) {
-    if (!DT && !PDT)
-      return;
-
-    if (Strategy == UpdateStrategy::Lazy) {
-      PendUpdates.reserve(PendUpdates.size() + Updates.size());
-      for (const auto &U : Updates)
-        if (!isSelfDominance(U))
-          PendUpdates.push_back(U);
-
-      return;
-    }
-
-    if (DT)
-      DT->applyUpdates(Updates);
-    if (PDT)
-      PDT->applyUpdates(Updates);
-  }
+  void applyUpdates(ArrayRef<typename DomTreeT::UpdateType> Updates);
 
   /// Submit updates to all available trees. It will also
   /// 1. discard duplicated updates,
@@ -210,58 +142,7 @@ class GenericDomTreeUpdater {
   /// 3. It is only legal to submit updates to an edge in the order CFG changes
   /// are made. The order you submit updates on different edges is not
   /// restricted.
-  void applyUpdatesPermissive(ArrayRef<typename DomTreeT::UpdateType> Updates) {
-    if (!DT && !PDT)
-      return;
-
-    SmallSet<std::pair<BasicBlockT *, BasicBlockT *>, 8> Seen;
-    SmallVector<typename DomTreeT::UpdateType, 8> DeduplicatedUpdates;
-    for (const auto &U : Updates) {
-      auto Edge = std::make_pair(U.getFrom(), U.getTo());
-      // Because it is illegal to submit updates that have already been applied
-      // and updates to an edge need to be strictly ordered,
-      // it is safe to infer the existence of an edge from the first update
-      // to this edge.
-      // If the first update to an edge is "Delete", it means that the edge
-      // existed before. If the first update to an edge is "Insert", it means
-      // that the edge didn't exist before.
-      //
-      // For example, if the user submits {{Delete, A, B}, {Insert, A, B}},
-      // because
-      // 1. it is illegal to submit updates that have already been applied,
-      // i.e., user cannot delete an nonexistent edge,
-      // 2. updates to an edge need to be strictly ordered,
-      // So, initially edge A -> B existed.
-      // We can then safely ignore future updates to this edge and directly
-      // inspect the current CFG:
-      // a. If the edge still exists, because the user cannot insert an existent
-      // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and
-      // resulted in a no-op. DTU won't submit any update in this case.
-      // b. If the edge doesn't exist, we can then infer that {Delete, A, B}
-      // actually happened but {Insert, A, B} was an invalid update which never
-      // happened. DTU will submit {Delete, A, B} in this case.
-      if (!isSelfDominance(U) && Seen.count(Edge) == 0) {
-        Seen.insert(Edge);
-        // If the update doesn't appear in the CFG, it means that
-        // either the change isn't made or relevant operations
-        // result in a no-op.
-        if (isUpdateValid(U)) {
-          if (isLazy())
-            PendUpdates.push_back(U);
-          else
-            DeduplicatedUpdates.push_back(U);
-        }
-      }
-    }
-
-    if (Strategy == UpdateStrategy::Lazy)
-      return;
-
-    if (DT)
-      DT->applyUpdates(DeduplicatedUpdates);
-    if (PDT)
-      PDT->applyUpdates(DeduplicatedUpdates);
-  }
+  void applyUpdatesPermissive(ArrayRef<typename DomTreeT::UpdateType> Updates);
 
   ///@}
 
@@ -275,127 +156,22 @@ class GenericDomTreeUpdater {
   /// Flush DomTree updates and return DomTree.
   /// It flushes Deleted BBs if both trees are up-to-date.
   /// It must only be called when it has a DomTree.
-  DomTreeT &getDomTree() {
-    assert(DT && "Invalid acquisition of a null DomTree");
-    applyDomTreeUpdates();
-    dropOutOfDateUpdates();
-    return *DT;
-  }
+  DomTreeT &getDomTree();
 
   /// Flush PostDomTree updates and return PostDomTree.
   /// It flushes Deleted BBs if both trees are up-to-date.
   /// It must only be called when it has a PostDomTree.
-  PostDomTreeT &getPostDomTree() {
-    assert(PDT && "Invalid acquisition of a null PostDomTree");
-    applyPostDomTreeUpdates();
-    dropOutOfDateUpdates();
-    return *PDT;
-  }
+  PostDomTreeT &getPostDomTree();
 
   /// Apply all pending updates to available trees and flush all BasicBlocks
   /// awaiting deletion.
 
-  void flush() {
-    applyDomTreeUpdates();
-    applyPostDomTreeUpdates();
-    dropOutOfDateUpdates();
-  }
+  void flush();
 
   ///@}
 
   /// Debug method to help view the internal state of this class.
-  LLVM_DUMP_METHOD void dump() const {
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-    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 =
-        [&](typename ArrayRef<typename DomTreeT::UpdateType>::const_iterator
-                begin,
-            typename ArrayRef<typename DomTreeT::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() == DomTreeT::Insert)
-              OS << "Insert, ";
-            else
-              OS << "Delete, ";
-            BasicBlockT *From = U.getFrom();
-            if (From) {
-              auto S = From->getName();
-              if (!From->hasName())
-                S = "(no name)";
-              OS << S << "(" << From << "), ";
-            } else {
-              OS << "(badref), ";
-            }
-            BasicBlockT *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 (const auto *BB : DeletedBBs) {
-      OS << "  " << Index << " : ";
-      ++Index;
-      if (BB->hasName())
-        OS << BB->getName() << "(";
-      else
-        OS << "(no_name)(";
-      OS << BB << ")\n";
-    }
-#endif
-  }
+  LLVM_DUMP_METHOD void dump() const;
 
 protected:
   SmallVector<typename DomTreeT::UpdateType, 16> PendUpdates;
@@ -409,115 +185,30 @@ class GenericDomTreeUpdater {
   bool IsRecalculatingPostDomTree = false;
 
   /// Returns true if the update is self dominance.
-  bool isSelfDominance(typename DomTreeT::UpdateType Update) const {
-    // Won't affect DomTree and PostDomTree.
-    return Update.getFrom() == Update.getTo();
-  }
+  bool isSelfDominance(typename DomTreeT::UpdateType Update) const;
 
   /// Helper function to apply all pending DomTree updates.
-  void 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<typename DomTreeT::UpdateType>(I, E));
-      PendDTUpdateIndex = PendUpdates.size();
-    }
-  }
+  void applyDomTreeUpdates();
 
   /// Helper function to apply all pending PostDomTree updates.
-  void 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<typename DomTreeT::UpdateType>(I, E));
-      PendPDTUpdateIndex = PendUpdates.size();
-    }
-  }
+  void applyPostDomTreeUpdates();
 
   /// 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(typename DomTreeT::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::is_contained(successors(From), 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 == DomTreeT::Insert && !HasEdge)
-      return false;
-
-    // Edge exists in IR.
-    if (Kind == DomTreeT::Delete && HasEdge)
-      return false;
-
-    return true;
-  }
+  bool isUpdateValid(typename DomTreeT::UpdateType Update) const;
 
   /// Erase Basic Block node that has been unlinked from Function
   /// in the DomTree and PostDomTree.
-  void eraseDelBBNode(BasicBlockT *DelBB) {
-    if (DT && !IsRecalculatingDomTree)
-      if (DT->getNode(DelBB))
-        DT->eraseNode(DelBB);
-
-    if (PDT && !IsRecalculatingPostDomTree)
-      if (PDT->getNode(DelBB))
-        PDT->eraseNode(DelBB);
-  }
+  void eraseDelBBNode(BasicBlockT *DelBB);
 
   /// Helper function to flush deleted BasicBlocks if all available
   /// trees are up-to-date.
-  void tryFlushDeletedBB() {
-    if (!hasPendingUpdates())
-      derived().forceFlushDeletedBB();
-  }
+  void tryFlushDeletedBB();
 
   /// Drop all updates applied by all available trees and delete BasicBlocks if
   /// all available trees are up-to-date.
-  void dropOutOfDateUpdates() {
-    if (Strategy == 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;
-  }
+  void dropOutOfDateUpdates();
 };
 
 } // namespace llvm
diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
new file mode 100644
index 0000000000000..ec6c345b994ac
--- /dev/null
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
@@ -0,0 +1,477 @@
+//===- GenericDomTreeUpdaterImpl.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the GenericDomTreeUpdater class. This file should only
+// be included by files that implement a specialization of the relevant
+// templates. Currently these are:
+// - llvm/lib/Analysis/DomTreeUpdater.cpp
+// - llvm/lib/CodeGen/MachineDomTreeUpdater.cpp
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
+#define LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
+
+#include "llvm/Analysis/GenericDomTreeUpdater.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+DerivedT &GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::derived() {
+  return *static_cast<DerivedT *>(this);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+const DerivedT &
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::derived() const {
+  return *static_cast<const DerivedT *>(this);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    UpdateStrategy Strategy_)
+    : Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    DomTreeT &DT_, UpdateStrategy Strategy_)
+    : DT(&DT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    DomTreeT *DT_, UpdateStrategy Strategy_)
+    : DT(DT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    PostDomTreeT &PDT_, UpdateStrategy Strategy_)
+    : PDT(&PDT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    PostDomTreeT *PDT_, UpdateStrategy Strategy_)
+    : PDT(PDT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    DomTreeT &DT_, PostDomTreeT &PDT_, UpdateStrategy Strategy_)
+    : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
+    DomTreeT *DT_, PostDomTreeT *PDT_, UpdateStrategy Strategy_)
+    : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+GenericDomTreeUpdater<DerivedT, DomTreeT,
+                      PostDomTreeT>::~GenericDomTreeUpdater() {
+  flush();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isLazy() const {
+  return Strategy == UpdateStrategy::Lazy;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isEager() const {
+  return Strategy == UpdateStrategy::Eager;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::hasDomTree()
+    const {
+  return DT != nullptr;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::hasPostDomTree()
+    const {
+  return DT != nullptr;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::hasPendingDeletedBB() const {
+  return !DeletedBBs.empty();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
+    isBBPendingDeletion(BasicBlockT *DelBB) const {
+  if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
+    return false;
+  return DeletedBBs.contains(DelBB);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::hasPendingUpdates() const {
+  return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::hasPendingDomTreeUpdates() const {
+  if (!DT)
+    return false;
+  return PendUpdates.size() != PendDTUpdateIndex;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::hasPendingPostDomTreeUpdates() const {
+  if (!PDT)
+    return false;
+  return PendUpdates.size() != PendPDTUpdateIndex;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+template <typename FuncT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::recalculate(
+    FuncT &F) {
+  if (Strategy == UpdateStrategy::Eager) {
+    if (DT)
+      DT->recalculate(F);
+    if (PDT)
+      PDT->recalculate(F);
+    return;
+  }
+
+  // There is little performance gain if we pend the recalculation under
+  // Lazy UpdateStrategy so we recalculate available trees immediately.
+
+  // 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.
+  derived().forceFlushDeletedBB();
+  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();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::applyUpdates(
+    ArrayRef<typename DomTreeT::UpdateType> Updates) {
+  if (!DT && !PDT)
+    return;
+
+  if (Strategy == UpdateStrategy::Lazy) {
+    PendUpdates.reserve(PendUpdates.size() + Updates.size());
+    for (const auto &U : Updates)
+      if (!isSelfDominance(U))
+        PendUpdates.push_back(U);
+
+    return;
+  }
+
+  if (DT)
+    DT->applyUpdates(Updates);
+  if (PDT)
+    PDT->applyUpdates(Updates);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
+    applyUpdatesPermissive(ArrayRef<typename DomTreeT::UpdateType> Updates) {
+  if (!DT && !PDT)
+    return;
+
+  SmallSet<std::pair<BasicBlockT *, BasicBlockT *>, 8> Seen;
+  SmallVector<typename DomTreeT::UpdateType, 8> DeduplicatedUpdates;
+  for (const auto &U : Updates) {
+    auto Edge = std::make_pair(U.getFrom(), U.getTo());
+    // Because it is illegal to submit updates that have already been applied
+    // and updates to an edge need to be strictly ordered,
+    // it is safe to infer the existence of an edge from the first update
+    // to this edge.
+    // If the first update to an edge is "Delete", it means that the edge
+    // existed before. If the first update to an edge is "Insert", it means
+    // that the edge didn't exist before.
+    //
+    // For example, if the user submits {{Delete, A, B}, {Insert, A, B}},
+    // because
+    // 1. it is illegal to submit updates that have already been applied,
+    // i.e., user cannot delete an nonexistent edge,
+    // 2. updates to an edge need to be strictly ordered,
+    // So, initially edge A -> B existed.
+    // We can then safely ignore future updates to this edge and directly
+    // inspect the current CFG:
+    // a. If the edge still exists, because the user cannot insert an existent
+    // edge, so both {Delete, A, B}, {Insert, A, B} actually happened and
+    // resulted in a no-op. DTU won't submit any update in this case.
+    // b. If the edge doesn't exist, we can then infer that {Delete, A, B}
+    // actually happened but {Insert, A, B} was an invalid update which never
+    // happened. DTU will submit {Delete, A, B} in this case.
+    if (!isSelfDominance(U) && Seen.count(Edge) == 0) {
+      Seen.insert(Edge);
+      // If the update doesn't appear in the CFG, it means that
+      // either the change isn't made or relevant operations
+      // result in a no-op.
+      if (isUpdateValid(U)) {
+        if (isLazy())
+          PendUpdates.push_back(U);
+        else
+          DeduplicatedUpdates.push_back(U);
+      }
+    }
+  }
+
+  if (Strategy == UpdateStrategy::Lazy)
+    return;
+
+  if (DT)
+    DT->applyUpdates(DeduplicatedUpdates);
+  if (PDT)
+    PDT->applyUpdates(DeduplicatedUpdates);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+DomTreeT &
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::getDomTree() {
+  assert(DT && "Invalid acquisition of a null DomTree");
+  applyDomTreeUpdates();
+  dropOutOfDateUpdates();
+  return *DT;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+PostDomTreeT &
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::getPostDomTree() {
+  assert(PDT && "Invalid acquisition of a null PostDomTree");
+  applyPostDomTreeUpdates();
+  dropOutOfDateUpdates();
+  return *PDT;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::flush() {
+  applyDomTreeUpdates();
+  applyPostDomTreeUpdates();
+  dropOutOfDateUpdates();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+LLVM_DUMP_METHOD void
+GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::dump() const {
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  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 =
+      [&](typename ArrayRef<typename DomTreeT::UpdateType>::const_iterator
+              begin,
+          typename ArrayRef<typename DomTreeT::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() == DomTreeT::Insert)
+            OS << "Insert, ";
+          else
+            OS << "Delete, ";
+          BasicBlockT *From = U.getFrom();
+          if (From) {
+            auto S = From->getName();
+            if (!From->hasName())
+              S = "(no name)";
+            OS << S << "(" << From << "), ";
+          } else {
+            OS << "(badref), ";
+          }
+          BasicBlockT *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 (const auto *BB : DeletedBBs) {
+    OS << "  " << Index << " : ";
+    ++Index;
+    if (BB->hasName())
+      OS << BB->getName() << "(";
+    else
+      OS << "(no_name)(";
+    OS << BB << ")\n";
+  }
+#endif
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isSelfDominance(
+    typename DomTreeT::UpdateType Update) const {
+  // Won't affect DomTree and PostDomTree.
+  return Update.getFrom() == Update.getTo();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::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<typename DomTreeT::UpdateType>(I, E));
+    PendDTUpdateIndex = PendUpdates.size();
+  }
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::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<typename DomTreeT::UpdateType>(I, E));
+    PendPDTUpdateIndex = PendUpdates.size();
+  }
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isUpdateValid(
+    typename DomTreeT::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::is_contained(successors(From), 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 == DomTreeT::Insert && !HasEdge)
+    return false;
+
+  // Edge exists in IR.
+  if (Kind == DomTreeT::Delete && HasEdge)
+    return false;
+
+  return true;
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::eraseDelBBNode(
+    BasicBlockT *DelBB) {
+  if (DT && !IsRecalculatingDomTree)
+    if (DT->getNode(DelBB))
+      DT->eraseNode(DelBB);
+
+  if (PDT && !IsRecalculatingPostDomTree)
+    if (PDT->getNode(DelBB))
+      PDT->eraseNode(DelBB);
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::tryFlushDeletedBB() {
+  if (!hasPendingUpdates())
+    derived().forceFlushDeletedBB();
+}
+
+template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
+void GenericDomTreeUpdater<DerivedT, DomTreeT,
+                           PostDomTreeT>::dropOutOfDateUpdates() {
+  if (Strategy == 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;
+}
+
+} // namespace llvm
+
+#endif // LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
diff --git a/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h b/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h
index 9e59ba5f01ab7..e08b6b54c8e70 100644
--- a/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h
+++ b/llvm/include/llvm/CodeGen/MachineDomTreeUpdater.h
@@ -14,18 +14,13 @@
 #ifndef LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H
 #define LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H
 
-#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Analysis/GenericDomTreeUpdater.h"
 #include "llvm/CodeGen/MachineDominators.h"
-#include "llvm/CodeGen/MachinePostDominators.h"
-#include "llvm/IR/ValueHandle.h"
-#include "llvm/Support/Compiler.h"
-#include <cstddef>
-#include <functional>
-#include <vector>
 
 namespace llvm {
 
+class MachinePostDominatorTree;
+
 class MachineDomTreeUpdater
     : public GenericDomTreeUpdater<MachineDomTreeUpdater, MachineDominatorTree,
                                    MachinePostDominatorTree> {
@@ -67,5 +62,10 @@ class MachineDomTreeUpdater
 
 extern template class GenericDomTreeUpdater<
     MachineDomTreeUpdater, MachineDominatorTree, MachinePostDominatorTree>;
+
+extern template void
+GenericDomTreeUpdater<MachineDomTreeUpdater, MachineDominatorTree,
+                      MachinePostDominatorTree>::recalculate(MachineFunction
+                                                                 &MF);
 } // namespace llvm
 #endif // LLVM_CODEGEN_MACHINEDOMTREEUPDATER_H
diff --git a/llvm/lib/Analysis/DomTreeUpdater.cpp b/llvm/lib/Analysis/DomTreeUpdater.cpp
index 676cb87210176..6895317c1d03a 100644
--- a/llvm/lib/Analysis/DomTreeUpdater.cpp
+++ b/llvm/lib/Analysis/DomTreeUpdater.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/Analysis/GenericDomTreeUpdaterImpl.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
@@ -26,6 +27,10 @@ namespace llvm {
 template class GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
                                      PostDominatorTree>;
 
+template void
+GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
+                      PostDominatorTree>::recalculate(Function &F);
+
 bool DomTreeUpdater::forceFlushDeletedBB() {
   if (DeletedBBs.empty())
     return false;
@@ -94,4 +99,23 @@ void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
   new UnreachableInst(DelBB->getContext(), DelBB);
 }
 
+LLVM_DUMP_METHOD
+void DomTreeUpdater::dump() const {
+  Base::dump();
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  raw_ostream &OS = dbgs();
+  OS << "Pending Callbacks:\n";
+  int Index = 0;
+  for (const auto &BB : Callbacks) {
+    OS << "  " << Index << " : ";
+    ++Index;
+    if (BB->hasName())
+      OS << BB->getName() << "(";
+    else
+      OS << "(no_name)(";
+    OS << BB << ")\n";
+  }
+#endif
+}
+
 } // namespace llvm
diff --git a/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp b/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp
index 86b3185ca90a3..afffafb245e67 100644
--- a/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp
+++ b/llvm/lib/CodeGen/MachineDomTreeUpdater.cpp
@@ -13,9 +13,8 @@
 
 #include "llvm/CodeGen/MachineDomTreeUpdater.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/Analysis/GenericDomTreeUpdaterImpl.h"
 #include "llvm/CodeGen/MachinePostDominators.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/Instructions.h"
 #include "llvm/Support/GenericDomTree.h"
 #include <algorithm>
 #include <functional>
@@ -26,6 +25,11 @@ namespace llvm {
 template class GenericDomTreeUpdater<
     MachineDomTreeUpdater, MachineDominatorTree, MachinePostDominatorTree>;
 
+template void
+GenericDomTreeUpdater<MachineDomTreeUpdater, MachineDominatorTree,
+                      MachinePostDominatorTree>::recalculate(MachineFunction
+                                                                 &MF);
+
 bool MachineDomTreeUpdater::forceFlushDeletedBB() {
   if (DeletedBBs.empty())
     return false;

>From e96e6624c2adbbd650f074891d3580f36b80acfc Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Fri, 28 Jun 2024 18:06:10 +0800
Subject: [PATCH 2/2] Move trivial functions to header

---
 .../llvm/Analysis/GenericDomTreeUpdater.h     |  72 +++++++---
 .../llvm/Analysis/GenericDomTreeUpdaterImpl.h | 124 ------------------
 2 files changed, 51 insertions(+), 145 deletions(-)

diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
index 1a86398e4fc68..644230264bfe0 100644
--- a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
@@ -22,61 +22,84 @@ namespace llvm {
 
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 class GenericDomTreeUpdater {
-  DerivedT &derived();
-  const DerivedT &derived() const;
+  DerivedT &derived() { return *static_cast<DerivedT *>(this); }
+  const DerivedT &derived() const {
+    return *static_cast<const DerivedT *>(this);
+  }
 
 public:
   enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
   using BasicBlockT = typename DomTreeT::NodeType;
 
-  explicit GenericDomTreeUpdater(UpdateStrategy Strategy_);
-  GenericDomTreeUpdater(DomTreeT &DT_, UpdateStrategy Strategy_);
-  GenericDomTreeUpdater(DomTreeT *DT_, UpdateStrategy Strategy_);
-  GenericDomTreeUpdater(PostDomTreeT &PDT_, UpdateStrategy Strategy_);
-  GenericDomTreeUpdater(PostDomTreeT *PDT_, UpdateStrategy Strategy_);
+  explicit GenericDomTreeUpdater(UpdateStrategy Strategy_)
+      : Strategy(Strategy_) {}
+  GenericDomTreeUpdater(DomTreeT &DT_, UpdateStrategy Strategy_)
+      : DT(&DT_), Strategy(Strategy_) {}
+  GenericDomTreeUpdater(DomTreeT *DT_, UpdateStrategy Strategy_)
+      : DT(DT_), Strategy(Strategy_) {}
+  GenericDomTreeUpdater(PostDomTreeT &PDT_, UpdateStrategy Strategy_)
+      : PDT(&PDT_), Strategy(Strategy_) {}
+  GenericDomTreeUpdater(PostDomTreeT *PDT_, UpdateStrategy Strategy_)
+      : PDT(PDT_), Strategy(Strategy_) {}
   GenericDomTreeUpdater(DomTreeT &DT_, PostDomTreeT &PDT_,
-                        UpdateStrategy Strategy_);
+                        UpdateStrategy Strategy_)
+      : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
   GenericDomTreeUpdater(DomTreeT *DT_, PostDomTreeT *PDT_,
-                        UpdateStrategy Strategy_);
+                        UpdateStrategy Strategy_)
+      : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
 
-  ~GenericDomTreeUpdater();
+  ~GenericDomTreeUpdater() { flush(); }
 
   /// Returns true if the current strategy is Lazy.
-  bool isLazy() const;
+  bool isLazy() const { return Strategy == UpdateStrategy::Lazy; }
 
   /// Returns true if the current strategy is Eager.
-  bool isEager() const;
+  bool isEager() const { return Strategy == UpdateStrategy::Eager; }
 
   /// Returns true if it holds a DomTreeT.
-  bool hasDomTree() const;
+  bool hasDomTree() const { return DT != nullptr; }
 
   /// Returns true if it holds a PostDomTreeT.
-  bool hasPostDomTree() const;
+  bool hasPostDomTree() const { return PDT != nullptr; }
 
   /// Returns true if there is BasicBlockT 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;
+  bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); }
 
   /// Returns true if DelBB is awaiting deletion.
   /// Returns false under Eager UpdateStrategy.
-  bool isBBPendingDeletion(BasicBlockT *DelBB) const;
+  bool isBBPendingDeletion(BasicBlockT *DelBB) const {
+    if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
+      return false;
+    return DeletedBBs.contains(DelBB);
+  }
 
   /// 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 MachineBasicBlock awaiting deletion.
   /// Returns false under Eager UpdateStrategy.
-  bool hasPendingUpdates() const;
+  bool hasPendingUpdates() const {
+    return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
+  }
 
   /// Returns true if there are DomTreeT updates queued.
   /// Returns false under Eager UpdateStrategy or DT is nullptr.
-  bool hasPendingDomTreeUpdates() const;
+  bool hasPendingDomTreeUpdates() const {
+    if (!DT)
+      return false;
+    return PendUpdates.size() != PendDTUpdateIndex;
+  }
 
   /// Returns true if there are PostDomTreeT updates queued.
   /// Returns false under Eager UpdateStrategy or PDT is nullptr.
-  bool hasPendingPostDomTreeUpdates() const;
+  bool hasPendingPostDomTreeUpdates() const {
+    if (!PDT)
+      return false;
+    return PendUpdates.size() != PendPDTUpdateIndex;
+  }
 
   ///@{
   /// \name Mutation APIs
@@ -166,7 +189,11 @@ class GenericDomTreeUpdater {
   /// Apply all pending updates to available trees and flush all BasicBlocks
   /// awaiting deletion.
 
-  void flush();
+  void flush() {
+    applyDomTreeUpdates();
+    applyPostDomTreeUpdates();
+    dropOutOfDateUpdates();
+  }
 
   ///@}
 
@@ -185,7 +212,10 @@ class GenericDomTreeUpdater {
   bool IsRecalculatingPostDomTree = false;
 
   /// Returns true if the update is self dominance.
-  bool isSelfDominance(typename DomTreeT::UpdateType Update) const;
+  bool isSelfDominance(typename DomTreeT::UpdateType Update) const {
+    // Won't affect DomTree and PostDomTree.
+    return Update.getFrom() == Update.getTo();
+  }
 
   /// Helper function to apply all pending DomTree updates.
   void applyDomTreeUpdates();
diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
index ec6c345b994ac..35c54a6062bfd 100644
--- a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
@@ -22,116 +22,6 @@
 
 namespace llvm {
 
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-DerivedT &GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::derived() {
-  return *static_cast<DerivedT *>(this);
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-const DerivedT &
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::derived() const {
-  return *static_cast<const DerivedT *>(this);
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    UpdateStrategy Strategy_)
-    : Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    DomTreeT &DT_, UpdateStrategy Strategy_)
-    : DT(&DT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    DomTreeT *DT_, UpdateStrategy Strategy_)
-    : DT(DT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    PostDomTreeT &PDT_, UpdateStrategy Strategy_)
-    : PDT(&PDT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    PostDomTreeT *PDT_, UpdateStrategy Strategy_)
-    : PDT(PDT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    DomTreeT &DT_, PostDomTreeT &PDT_, UpdateStrategy Strategy_)
-    : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::GenericDomTreeUpdater(
-    DomTreeT *DT_, PostDomTreeT *PDT_, UpdateStrategy Strategy_)
-    : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-GenericDomTreeUpdater<DerivedT, DomTreeT,
-                      PostDomTreeT>::~GenericDomTreeUpdater() {
-  flush();
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isLazy() const {
-  return Strategy == UpdateStrategy::Lazy;
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isEager() const {
-  return Strategy == UpdateStrategy::Eager;
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::hasDomTree()
-    const {
-  return DT != nullptr;
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::hasPostDomTree()
-    const {
-  return DT != nullptr;
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT,
-                           PostDomTreeT>::hasPendingDeletedBB() const {
-  return !DeletedBBs.empty();
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
-    isBBPendingDeletion(BasicBlockT *DelBB) const {
-  if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
-    return false;
-  return DeletedBBs.contains(DelBB);
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT,
-                           PostDomTreeT>::hasPendingUpdates() const {
-  return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT,
-                           PostDomTreeT>::hasPendingDomTreeUpdates() const {
-  if (!DT)
-    return false;
-  return PendUpdates.size() != PendDTUpdateIndex;
-}
-
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT,
-                           PostDomTreeT>::hasPendingPostDomTreeUpdates() const {
-  if (!PDT)
-    return false;
-  return PendUpdates.size() != PendPDTUpdateIndex;
-}
-
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 template <typename FuncT>
 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::recalculate(
@@ -258,13 +148,6 @@ GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::getPostDomTree() {
   return *PDT;
 }
 
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::flush() {
-  applyDomTreeUpdates();
-  applyPostDomTreeUpdates();
-  dropOutOfDateUpdates();
-}
-
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 LLVM_DUMP_METHOD void
 GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::dump() const {
@@ -360,13 +243,6 @@ GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::dump() const {
 #endif
 }
 
-template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
-bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isSelfDominance(
-    typename DomTreeT::UpdateType Update) const {
-  // Won't affect DomTree and PostDomTree.
-  return Update.getFrom() == Update.getTo();
-}
-
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 void GenericDomTreeUpdater<DerivedT, DomTreeT,
                            PostDomTreeT>::applyDomTreeUpdates() {



More information about the llvm-commits mailing list