<div dir="auto"><div><div dir="ltr"><br>I'm hoping rG5da1671bf823 fixed them. Please let me know if not and I will revert.</div><div style="color:rgb(136,136,136)" dir="auto"><div dir="ltr"><br style="font-family:sans-serif;font-size:12.8px"></div></div>Alina<br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 9, 2020, 6:44 PM Michael Kruse <<a href="mailto:llvm-commits@meinersbur.de">llvm-commits@meinersbur.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This broke the Windows build:<br>
<a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-win-fast/builds/14172" rel="noreferrer noreferrer" target="_blank">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-win-fast/builds/14172</a><br>
<br>
Michael<br>
<br>
Am Do., 9. Apr. 2020 um 20:09 Uhr schrieb Alina Sbirlea via<br>
llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" rel="noreferrer">llvm-commits@lists.llvm.org</a>>:<br>
><br>
><br>
> Author: Alina Sbirlea<br>
> Date: 2020-04-09T18:08:39-07:00<br>
> New Revision: a90374988e4eb8c50d91e11f4e61cdbd5debb235<br>
><br>
> URL: <a href="https://github.com/llvm/llvm-project/commit/a90374988e4eb8c50d91e11f4e61cdbd5debb235" rel="noreferrer noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/a90374988e4eb8c50d91e11f4e61cdbd5debb235</a><br>
> DIFF: <a href="https://github.com/llvm/llvm-project/commit/a90374988e4eb8c50d91e11f4e61cdbd5debb235.diff" rel="noreferrer noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/a90374988e4eb8c50d91e11f4e61cdbd5debb235.diff</a><br>
><br>
> LOG: [DomTree] Replace ChildrenGetter with GraphTraits over GraphDiff.<br>
><br>
> Summary:<br>
> This replaces the ChildrenGetter inside the DominatorTree with<br>
> GraphTraits over a GraphDiff object, an object which encapsulated the<br>
> view of the previous CFG.<br>
> This also simplifies the extentions in clang which use DominatorTree, as<br>
> GraphDiff also filters nullptrs.<br>
><br>
> Reviewers: kuhar, dblaikie, NutshellySima<br>
><br>
> Subscribers: hiraditya, cfe-commits, llvm-commits<br>
><br>
> Tags: #clang<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D77341" rel="noreferrer noreferrer" target="_blank">https://reviews.llvm.org/D77341</a><br>
><br>
> Added:<br>
><br>
><br>
> Modified:<br>
>     clang/include/clang/Analysis/Analyses/Dominators.h<br>
>     llvm/include/llvm/IR/CFGDiff.h<br>
>     llvm/include/llvm/IR/Dominators.h<br>
>     llvm/include/llvm/Support/GenericDomTree.h<br>
>     llvm/include/llvm/Support/GenericDomTreeConstruction.h<br>
>     llvm/lib/IR/Dominators.cpp<br>
><br>
> Removed:<br>
><br>
><br>
><br>
> ################################################################################<br>
> diff  --git a/clang/include/clang/Analysis/Analyses/Dominators.h b/clang/include/clang/Analysis/Analyses/Dominators.h<br>
> index 061c98137da2..c0cfc186c365 100644<br>
> --- a/clang/include/clang/Analysis/Analyses/Dominators.h<br>
> +++ b/clang/include/clang/Analysis/Analyses/Dominators.h<br>
> @@ -275,76 +275,6 @@ class ControlDependencyCalculator : public ManagedAnalysis {<br>
><br>
>  namespace llvm {<br>
><br>
> -/// Clang's CFG contains nullpointers for unreachable succesors, e.g. when an<br>
> -/// if statement's condition is always false, it's 'then' branch is represented<br>
> -/// with a nullptr. This however will result in a nullpointer derefernece for<br>
> -/// dominator tree calculation.<br>
> -///<br>
> -/// To circumvent this, let's just crudely specialize the children getters<br>
> -/// used in LLVM's dominator tree builder.<br>
> -namespace DomTreeBuilder {<br>
> -<br>
> -using ClangCFGDomChildrenGetter =<br>
> -SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<<br>
> -                                                             /*Inverse=*/false>;<br>
> -<br>
> -template <><br>
> -template <><br>
> -inline ClangCFGDomChildrenGetter::ResultTy ClangCFGDomChildrenGetter::Get(<br>
> -    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {<br>
> -  auto RChildren = reverse(children<NodePtr>(N));<br>
> -  ResultTy Ret(RChildren.begin(), RChildren.end());<br>
> -  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());<br>
> -  return Ret;<br>
> -}<br>
> -<br>
> -using ClangCFGDomReverseChildrenGetter =<br>
> -SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<<br>
> -                                                              /*Inverse=*/true>;<br>
> -<br>
> -template <><br>
> -template <><br>
> -inline ClangCFGDomReverseChildrenGetter::ResultTy<br>
> -ClangCFGDomReverseChildrenGetter::Get(<br>
> -    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {<br>
> -  auto IChildren = inverse_children<NodePtr>(N);<br>
> -  ResultTy Ret(IChildren.begin(), IChildren.end());<br>
> -  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());<br>
> -  return Ret;<br>
> -}<br>
> -<br>
> -using ClangCFGPostDomChildrenGetter =<br>
> -SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<<br>
> -                                                             /*Inverse=*/false>;<br>
> -<br>
> -template <><br>
> -template <><br>
> -inline ClangCFGPostDomChildrenGetter::ResultTy<br>
> -ClangCFGPostDomChildrenGetter::Get(<br>
> -    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {<br>
> -  auto RChildren = reverse(children<NodePtr>(N));<br>
> -  ResultTy Ret(RChildren.begin(), RChildren.end());<br>
> -  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());<br>
> -  return Ret;<br>
> -}<br>
> -<br>
> -using ClangCFGPostDomReverseChildrenGetter =<br>
> -SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<<br>
> -                                                              /*Inverse=*/true>;<br>
> -<br>
> -template <><br>
> -template <><br>
> -inline ClangCFGPostDomReverseChildrenGetter::ResultTy<br>
> -ClangCFGPostDomReverseChildrenGetter::Get(<br>
> -    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {<br>
> -  auto IChildren = inverse_children<NodePtr>(N);<br>
> -  ResultTy Ret(IChildren.begin(), IChildren.end());<br>
> -  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());<br>
> -  return Ret;<br>
> -}<br>
> -<br>
> -} // end of namespace DomTreeBuilder<br>
> -<br>
>  //===-------------------------------------<br>
>  /// DominatorTree GraphTraits specialization so the DominatorTree can be<br>
>  /// iterable by generic graph iterators.<br>
><br>
> diff  --git a/llvm/include/llvm/IR/CFGDiff.h b/llvm/include/llvm/IR/CFGDiff.h<br>
> index c50db0de79a3..5f2b5c709324 100644<br>
> --- a/llvm/include/llvm/IR/CFGDiff.h<br>
> +++ b/llvm/include/llvm/IR/CFGDiff.h<br>
> @@ -195,6 +195,23 @@ template <typename NodePtr, bool InverseGraph = false> class GraphDiff {<br>
>  #endif<br>
>  };<br>
><br>
> +namespace detail {<br>
> +template <typename Range><br>
> +auto reverse_if_helper(Range &&R, std::integral_constant<bool, false>) {<br>
> +  return std::forward<Range>(R);<br>
> +}<br>
> +<br>
> +template <typename Range><br>
> +auto reverse_if_helper(Range &&R, std::integral_constant<bool, true>) {<br>
> +  return llvm::reverse(std::forward<Range>(R));<br>
> +}<br>
> +<br>
> +template <bool B, typename Range> auto reverse_if(Range &&R) {<br>
> +  return reverse_if_helper(std::forward<Range>(R),<br>
> +                           std::integral_constant<bool, B>{});<br>
> +}<br>
> +} // namespace detail<br>
> +<br>
>  template <typename GraphT, bool InverseGraph = false, bool InverseEdge = false,<br>
>            typename GT = GraphTraits<GraphT>><br>
>  struct CFGViewChildren {<br>
> @@ -211,9 +228,10 @@ struct CFGViewChildren {<br>
><br>
>      // filter iterator init:<br>
>      auto R = make_range(GT::child_begin(N.second), GT::child_end(N.second));<br>
> +    auto RR = detail::reverse_if<!InverseEdge>(R);<br>
>      // This lambda is copied into the iterators and persists to callers, ensure<br>
>      // captures are by value or otherwise have sufficient lifetime.<br>
> -    auto First = make_filter_range(makeChildRange(R, N.first), [N](NodeRef C) {<br>
> +    auto First = make_filter_range(makeChildRange(RR, N.first), [N](NodeRef C) {<br>
>        return !C.first->ignoreChild(N.second, C.second, InverseEdge);<br>
>      });<br>
><br>
><br>
> diff  --git a/llvm/include/llvm/IR/Dominators.h b/llvm/include/llvm/IR/Dominators.h<br>
> index 6a14785a6cc3..0c98902c72c8 100644<br>
> --- a/llvm/include/llvm/IR/Dominators.h<br>
> +++ b/llvm/include/llvm/IR/Dominators.h<br>
> @@ -44,6 +44,9 @@ using BBPostDomTree = PostDomTreeBase<BasicBlock>;<br>
><br>
>  using BBUpdates = ArrayRef<llvm::cfg::Update<BasicBlock *>>;<br>
><br>
> +using BBDomTreeGraphDiff = GraphDiff<BasicBlock *, false>;<br>
> +using BBPostDomTreeGraphDiff = GraphDiff<BasicBlock *, true>;<br>
> +<br>
>  extern template void Calculate<BBDomTree>(BBDomTree &DT);<br>
>  extern template void CalculateWithUpdates<BBDomTree>(BBDomTree &DT,<br>
>                                                       BBUpdates U);<br>
> @@ -62,8 +65,10 @@ extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT,<br>
>                                                 BasicBlock *From,<br>
>                                                 BasicBlock *To);<br>
><br>
> -extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT, BBUpdates);<br>
> -extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT, BBUpdates);<br>
> +extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT,<br>
> +                                             BBDomTreeGraphDiff &);<br>
> +extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT,<br>
> +                                                 BBPostDomTreeGraphDiff &);<br>
><br>
>  extern template bool Verify<BBDomTree>(const BBDomTree &DT,<br>
>                                         BBDomTree::VerificationLevel VL);<br>
><br>
> diff  --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h<br>
> index 1e1fc1fa2486..4159baa50dad 100644<br>
> --- a/llvm/include/llvm/Support/GenericDomTree.h<br>
> +++ b/llvm/include/llvm/Support/GenericDomTree.h<br>
> @@ -29,6 +29,7 @@<br>
>  #include "llvm/ADT/STLExtras.h"<br>
>  #include "llvm/ADT/SmallPtrSet.h"<br>
>  #include "llvm/ADT/SmallVector.h"<br>
> +#include "llvm/IR/CFGDiff.h"<br>
>  #include "llvm/Support/CFGUpdate.h"<br>
>  #include "llvm/Support/raw_ostream.h"<br>
>  #include <algorithm><br>
> @@ -205,7 +206,8 @@ void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,<br>
><br>
>  template <typename DomTreeT><br>
>  void ApplyUpdates(DomTreeT &DT,<br>
> -                  ArrayRef<typename DomTreeT::UpdateType> Updates);<br>
> +                  GraphDiff<typename DomTreeT::NodePtr,<br>
> +                            DomTreeT::IsPostDominator> &PreViewCFG);<br>
><br>
>  template <typename DomTreeT><br>
>  bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);<br>
> @@ -515,10 +517,13 @@ class DominatorTreeBase {<br>
>    /// The type of updates is the same for DomTreeBase<T> and PostDomTreeBase<T><br>
>    /// with the same template parameter T.<br>
>    ///<br>
> -  /// \param Updates An unordered sequence of updates to perform.<br>
> +  /// \param Updates An unordered sequence of updates to perform. The current<br>
> +  /// CFG and the reverse of these updates provides the pre-view of the CFG.<br>
>    ///<br>
>    void applyUpdates(ArrayRef<UpdateType> Updates) {<br>
> -    DomTreeBuilder::ApplyUpdates(*this, Updates);<br>
> +    GraphDiff<NodePtr, IsPostDominator> PreViewCFG(<br>
> +        Updates, /*ReverseApplyUpdates=*/true);<br>
> +    DomTreeBuilder::ApplyUpdates(*this, PreViewCFG);<br>
>    }<br>
><br>
>    /// Inform the dominator tree about a CFG edge insertion and update the tree.<br>
><br>
> diff  --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h<br>
> index a344f66c548e..2e848358bb5b 100644<br>
> --- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h<br>
> +++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h<br>
> @@ -58,6 +58,13 @@ struct SemiNCAInfo {<br>
>    using TreeNodePtr = DomTreeNodeBase<NodeT> *;<br>
>    using RootsT = decltype(DomTreeT::Roots);<br>
>    static constexpr bool IsPostDom = DomTreeT::IsPostDominator;<br>
> +  using GraphDiffT = GraphDiff<NodePtr, IsPostDom>;<br>
> +  using GraphDiffNodePair = std::pair<const GraphDiffT *, NodePtr>;<br>
> +  using GraphDiffInvNodePair = std::pair<const GraphDiffT *, Inverse<NodePtr>>;<br>
> +  using GraphDiffNodePairIfDomT =<br>
> +      std::conditional_t<!IsPostDom, GraphDiffInvNodePair, GraphDiffNodePair>;<br>
> +  using GraphDiffNodePairIfPDomT =<br>
> +      std::conditional_t<IsPostDom, GraphDiffInvNodePair, GraphDiffNodePair>;<br>
><br>
>    // Information record used by Semi-NCA during tree construction.<br>
>    struct InfoRec {<br>
> @@ -77,28 +84,27 @@ struct SemiNCAInfo {<br>
>    using UpdateT = typename DomTreeT::UpdateType;<br>
>    using UpdateKind = typename DomTreeT::UpdateKind;<br>
>    struct BatchUpdateInfo {<br>
> -    SmallVector<UpdateT, 4> Updates;<br>
> -    using NodePtrAndKind = PointerIntPair<NodePtr, 1, UpdateKind>;<br>
> -<br>
> -    // In order to be able to walk a CFG that is out of sync with the CFG<br>
> -    // DominatorTree last knew about, use the list of updates to reconstruct<br>
> -    // previous CFG versions of the current CFG. For each node, we store a set<br>
> -    // of its virtually added/deleted future successors and predecessors.<br>
> -    // Note that these children are from the future relative to what the<br>
> -    // DominatorTree knows about -- using them to gets us some snapshot of the<br>
> -    // CFG from the past (relative to the state of the CFG).<br>
> -    DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FutureSuccessors;<br>
> -    DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FuturePredecessors;<br>
> +    // Note: Updates inside PreViewCFG are aleady legalized.<br>
> +    BatchUpdateInfo(GraphDiffT &PreViewCFG)<br>
> +        : PreViewCFG(PreViewCFG),<br>
> +          NumLegalized(PreViewCFG.getNumLegalizedUpdates()) {}<br>
> +<br>
>      // Remembers if the whole tree was recalculated at some point during the<br>
>      // current batch update.<br>
>      bool IsRecalculated = false;<br>
> +    GraphDiffT &PreViewCFG;<br>
> +    const size_t NumLegalized;<br>
>    };<br>
><br>
>    BatchUpdateInfo *BatchUpdates;<br>
>    using BatchUpdatePtr = BatchUpdateInfo *;<br>
> +  std::unique_ptr<GraphDiffT> EmptyGD;<br>
><br>
>    // If BUI is a nullptr, then there's no batch update in progress.<br>
> -  SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {}<br>
> +  SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {<br>
> +    if (!BatchUpdates)<br>
> +      EmptyGD = std::make_unique<GraphDiffT>();<br>
> +  }<br>
><br>
>    void clear() {<br>
>      NumToNode = {nullptr}; // Restore to initial state with a dummy start node.<br>
> @@ -107,67 +113,6 @@ struct SemiNCAInfo {<br>
>      // in progress, we need this information to continue it.<br>
>    }<br>
><br>
> -  template <bool Inverse><br>
> -  struct ChildrenGetter {<br>
> -    using ResultTy = SmallVector<NodePtr, 8>;<br>
> -<br>
> -    static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) {<br>
> -      auto RChildren = reverse(children<NodePtr>(N));<br>
> -      return ResultTy(RChildren.begin(), RChildren.end());<br>
> -    }<br>
> -<br>
> -    static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) {<br>
> -      auto IChildren = inverse_children<NodePtr>(N);<br>
> -      return ResultTy(IChildren.begin(), IChildren.end());<br>
> -    }<br>
> -<br>
> -    using Tag = std::integral_constant<bool, Inverse>;<br>
> -<br>
> -    // The function below is the core part of the batch updater. It allows the<br>
> -    // Depth Based Search algorithm to perform incremental updates in lockstep<br>
> -    // with updates to the CFG. We emulated lockstep CFG updates by getting its<br>
> -    // next snapshots by reverse-applying future updates.<br>
> -    static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) {<br>
> -      ResultTy Res = Get(N, Tag());<br>
> -      // If there's no batch update in progress, simply return node's children.<br>
> -      if (!BUI) return Res;<br>
> -<br>
> -      // CFG children are actually its *most current* children, and we have to<br>
> -      // reverse-apply the future updates to get the node's children at the<br>
> -      // point in time the update was performed.<br>
> -      auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors<br>
> -                                                    : BUI->FutureSuccessors;<br>
> -      auto FCIt = FutureChildren.find(N);<br>
> -      if (FCIt == FutureChildren.end()) return Res;<br>
> -<br>
> -      for (auto ChildAndKind : FCIt->second) {<br>
> -        const NodePtr Child = ChildAndKind.getPointer();<br>
> -        const UpdateKind UK = ChildAndKind.getInt();<br>
> -<br>
> -        // Reverse-apply the future update.<br>
> -        if (UK == UpdateKind::Insert) {<br>
> -          // If there's an insertion in the future, it means that the edge must<br>
> -          // exist in the current CFG, but was not present in it before.<br>
> -          assert(llvm::find(Res, Child) != Res.end()<br>
> -                 && "Expected child not found in the CFG");<br>
> -          Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end());<br>
> -          LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> "<br>
> -                            << BlockNamePrinter(Child) << "\n");<br>
> -        } else {<br>
> -          // If there's an deletion in the future, it means that the edge cannot<br>
> -          // exist in the current CFG, but existed in it before.<br>
> -          assert(llvm::find(Res, Child) == Res.end() &&<br>
> -                 "Unexpected child found in the CFG");<br>
> -          LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N)<br>
> -                            << " -> " << BlockNamePrinter(Child) << "\n");<br>
> -          Res.push_back(Child);<br>
> -        }<br>
> -      }<br>
> -<br>
> -      return Res;<br>
> -    }<br>
> -  };<br>
> -<br>
>    NodePtr getIDom(NodePtr BB) const {<br>
>      auto InfoIt = NodeToInfo.find(BB);<br>
>      if (InfoIt == NodeToInfo.end()) return nullptr;<br>
> @@ -235,8 +180,12 @@ struct SemiNCAInfo {<br>
>        NumToNode.push_back(BB);<br>
><br>
>        constexpr bool Direction = IsReverse != IsPostDom;  // XOR.<br>
> -      for (const NodePtr Succ :<br>
> -           ChildrenGetter<Direction>::Get(BB, BatchUpdates)) {<br>
> +      using DirectedNodeT =<br>
> +          std::conditional_t<Direction, Inverse<NodePtr>, NodePtr>;<br>
> +      using GraphDiffBBPair = std::pair<const GraphDiffT *, DirectedNodeT>;<br>
> +      const auto *GD = BatchUpdates ? &BatchUpdates->PreViewCFG : EmptyGD.get();<br>
> +      for (auto &Pair : children<GraphDiffBBPair>({GD, BB})) {<br>
> +        const NodePtr Succ = Pair.second;<br>
>          const auto SIT = NodeToInfo.find(Succ);<br>
>          // Don't visit nodes more than once but remember to collect<br>
>          // ReverseChildren.<br>
> @@ -371,7 +320,9 @@ struct SemiNCAInfo {<br>
>    // to CFG nodes within infinite loops.<br>
>    static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) {<br>
>      assert(N && "N must be a valid node");<br>
> -    return !ChildrenGetter<false>::Get(N, BUI).empty();<br>
> +    GraphDiffT EmptyGD;<br>
> +    auto &GD = BUI ? BUI->PreViewCFG : EmptyGD;<br>
> +    return !empty(children<GraphDiffNodePair>({&GD, N}));<br>
>    }<br>
><br>
>    static NodePtr GetEntryNode(const DomTreeT &DT) {<br>
> @@ -795,8 +746,11 @@ struct SemiNCAInfo {<br>
>          //<br>
>          // Invariant: there is an optimal path from `To` to TN with the minimum<br>
>          // depth being CurrentLevel.<br>
> -        for (const NodePtr Succ :<br>
> -             ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) {<br>
> +        GraphDiffT EmptyGD;<br>
> +        auto &GD = BUI ? BUI->PreViewCFG : EmptyGD;<br>
> +        for (auto &Pair :<br>
> +             children<GraphDiffNodePairIfPDomT>({&GD, TN->getBlock()})) {<br>
> +          const NodePtr Succ = Pair.second;<br>
>            const TreeNodePtr SuccTN = DT.getNode(Succ);<br>
>            assert(SuccTN &&<br>
>                   "Unreachable successor found at reachable insertion");<br>
> @@ -926,8 +880,12 @@ struct SemiNCAInfo {<br>
>      // the DomTree about it.<br>
>      // The check is O(N), so run it only in debug configuration.<br>
>      auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) {<br>
> -      auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI);<br>
> -      return llvm::find(Successors, SuccCandidate) != Successors.end();<br>
> +      GraphDiffT EmptyGD;<br>
> +      auto &GD = BUI ? BUI->PreViewCFG : EmptyGD;<br>
> +      for (auto &Pair : children<GraphDiffNodePairIfPDomT>({&GD, Of}))<br>
> +        if (Pair.second == SuccCandidate)<br>
> +          return true;<br>
> +      return false;<br>
>      };<br>
>      (void)IsSuccessor;<br>
>      assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!");<br>
> @@ -1013,15 +971,17 @@ struct SemiNCAInfo {<br>
>                                 const TreeNodePtr TN) {<br>
>      LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)<br>
>                        << "\n");<br>
> -    for (const NodePtr Pred :<br>
> -         ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) {<br>
> +    auto TNB = TN->getBlock();<br>
> +    GraphDiffT EmptyGD;<br>
> +    auto &GD = BUI ? BUI->PreViewCFG : EmptyGD;<br>
> +    for (auto &Pair : children<GraphDiffNodePairIfDomT>({&GD, TNB})) {<br>
> +      const NodePtr Pred = Pair.second;<br>
>        LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");<br>
>        if (!DT.getNode(Pred)) continue;<br>
><br>
> -      const NodePtr Support =<br>
> -          DT.findNearestCommonDominator(TN->getBlock(), Pred);<br>
> +      const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);<br>
>        LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n");<br>
> -      if (Support != TN->getBlock()) {<br>
> +      if (Support != TNB) {<br>
>          LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN)<br>
>                            << " is reachable from support "<br>
>                            << BlockNamePrinter(Support) << "\n");<br>
> @@ -1152,53 +1112,23 @@ struct SemiNCAInfo {<br>
>    //===--------------------- DomTree Batch Updater --------------------------===<br>
>    //~~<br>
><br>
> -  static void ApplyUpdates(DomTreeT &DT, ArrayRef<UpdateT> Updates) {<br>
> -    const size_t NumUpdates = Updates.size();<br>
> +  static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG) {<br>
> +    const size_t NumUpdates = PreViewCFG.getNumLegalizedUpdates();<br>
>      if (NumUpdates == 0)<br>
>        return;<br>
><br>
>      // Take the fast path for a single update and avoid running the batch update<br>
>      // machinery.<br>
>      if (NumUpdates == 1) {<br>
> -      const auto &Update = Updates.front();<br>
> +      UpdateT Update = PreViewCFG.popUpdateForIncrementalUpdates();<br>
>        if (Update.getKind() == UpdateKind::Insert)<br>
> -        DT.insertEdge(Update.getFrom(), Update.getTo());<br>
> +        InsertEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());<br>
>        else<br>
> -        DT.deleteEdge(Update.getFrom(), Update.getTo());<br>
> -<br>
> +        DeleteEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());<br>
>        return;<br>
>      }<br>
><br>
> -    BatchUpdateInfo BUI;<br>
> -    LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n");<br>
> -    cfg::LegalizeUpdates<NodePtr>(Updates, BUI.Updates, IsPostDom);<br>
> -<br>
> -    const size_t NumLegalized = BUI.Updates.size();<br>
> -    BUI.FutureSuccessors.reserve(NumLegalized);<br>
> -    BUI.FuturePredecessors.reserve(NumLegalized);<br>
> -<br>
> -    // Use the legalized future updates to initialize future successors and<br>
> -    // predecessors. Note that these sets will only decrease size over time, as<br>
> -    // the next CFG snapshots slowly approach the actual (current) CFG.<br>
> -    for (UpdateT &U : BUI.Updates) {<br>
> -      BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()});<br>
> -      BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()});<br>
> -    }<br>
> -<br>
> -#if 0<br>
> -    // FIXME: The LLVM_DEBUG macro only plays well with a modular<br>
> -    // build of LLVM when the header is marked as textual, but doing<br>
> -    // so causes redefinition errors.<br>
> -    LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n");<br>
> -    LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U<br>
> -                                           : reverse(BUI.Updates)) {<br>
> -      dbgs() << "\t";<br>
> -      U.dump();<br>
> -      dbgs() << "\n";<br>
> -    });<br>
> -    LLVM_DEBUG(dbgs() << "\n");<br>
> -#endif<br>
> -<br>
> +    BatchUpdateInfo BUI(PreViewCFG);<br>
>      // Recalculate the DominatorTree when the number of updates<br>
>      // exceeds a threshold, which usually makes direct updating slower than<br>
>      // recalculation. We select this threshold proportional to the<br>
> @@ -1208,21 +1138,21 @@ struct SemiNCAInfo {<br>
><br>
>      // Make unittests of the incremental algorithm work<br>
>      if (DT.DomTreeNodes.size() <= 100) {<br>
> -      if (NumLegalized > DT.DomTreeNodes.size())<br>
> +      if (BUI.NumLegalized > DT.DomTreeNodes.size())<br>
>          CalculateFromScratch(DT, &BUI);<br>
> -    } else if (NumLegalized > DT.DomTreeNodes.size() / 40)<br>
> +    } else if (BUI.NumLegalized > DT.DomTreeNodes.size() / 40)<br>
>        CalculateFromScratch(DT, &BUI);<br>
><br>
>      // If the DominatorTree was recalculated at some point, stop the batch<br>
>      // updates. Full recalculations ignore batch updates and look at the actual<br>
>      // CFG.<br>
> -    for (size_t i = 0; i < NumLegalized && !BUI.IsRecalculated; ++i)<br>
> +    for (size_t i = 0; i < BUI.NumLegalized && !BUI.IsRecalculated; ++i)<br>
>        ApplyNextUpdate(DT, BUI);<br>
>    }<br>
><br>
>    static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) {<br>
> -    assert(!BUI.Updates.empty() && "No updates to apply!");<br>
> -    UpdateT CurrentUpdate = BUI.Updates.pop_back_val();<br>
> +    // Popping the next update, will move the PreViewCFG to the next snapshot.<br>
> +    UpdateT CurrentUpdate = BUI.PreViewCFG.popUpdateForIncrementalUpdates();<br>
>  #if 0<br>
>      // FIXME: The LLVM_DEBUG macro only plays well with a modular<br>
>      // build of LLVM when the header is marked as textual, but doing<br>
> @@ -1231,21 +1161,6 @@ struct SemiNCAInfo {<br>
>      LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n");<br>
>  #endif<br>
><br>
> -    // Move to the next snapshot of the CFG by removing the reverse-applied<br>
> -    // current update. Since updates are performed in the same order they are<br>
> -    // legalized it's sufficient to pop the last item here.<br>
> -    auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()];<br>
> -    assert(FS.back().getPointer() == CurrentUpdate.getTo() &&<br>
> -           FS.back().getInt() == CurrentUpdate.getKind());<br>
> -    FS.pop_back();<br>
> -    if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom());<br>
> -<br>
> -    auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()];<br>
> -    assert(FP.back().getPointer() == CurrentUpdate.getFrom() &&<br>
> -           FP.back().getInt() == CurrentUpdate.getKind());<br>
> -    FP.pop_back();<br>
> -    if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo());<br>
> -<br>
>      if (CurrentUpdate.getKind() == UpdateKind::Insert)<br>
>        InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());<br>
>      else<br>
> @@ -1603,19 +1518,11 @@ void Calculate(DomTreeT &DT) {<br>
>  template <typename DomTreeT><br>
>  void CalculateWithUpdates(DomTreeT &DT,<br>
>                            ArrayRef<typename DomTreeT::UpdateType> Updates) {<br>
> -  // TODO: Move BUI creation in common method, reuse in ApplyUpdates.<br>
> -  typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI;<br>
> -  LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n");<br>
> -  cfg::LegalizeUpdates<typename DomTreeT::NodePtr>(Updates, BUI.Updates,<br>
> -                                                   DomTreeT::IsPostDominator);<br>
> -  const size_t NumLegalized = BUI.Updates.size();<br>
> -  BUI.FutureSuccessors.reserve(NumLegalized);<br>
> -  BUI.FuturePredecessors.reserve(NumLegalized);<br>
> -  for (auto &U : BUI.Updates) {<br>
> -    BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()});<br>
> -    BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()});<br>
> -  }<br>
> -<br>
> +  // FIXME: Updated to use the PreViewCFG and behave the same as until now.<br>
> +  // This behavior is however incorrect; this actually needs the PostViewCFG.<br>
> +  GraphDiff<typename DomTreeT::NodePtr, DomTreeT::IsPostDominator> PreViewCFG(<br>
> +      Updates, /*ReverseApplyUpdates=*/true);<br>
> +  typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI(PreViewCFG);<br>
>    SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, &BUI);<br>
>  }<br>
><br>
> @@ -1635,8 +1542,9 @@ void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,<br>
><br>
>  template <class DomTreeT><br>
>  void ApplyUpdates(DomTreeT &DT,<br>
> -                  ArrayRef<typename DomTreeT::UpdateType> Updates) {<br>
> -  SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, Updates);<br>
> +                  GraphDiff<typename DomTreeT::NodePtr,<br>
> +                            DomTreeT::IsPostDominator> &PreViewCFG) {<br>
> +  SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, PreViewCFG);<br>
>  }<br>
><br>
>  template <class DomTreeT><br>
><br>
> diff  --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp<br>
> index 4062ade645ba..a58380ff1f70 100644<br>
> --- a/llvm/lib/IR/Dominators.cpp<br>
> +++ b/llvm/lib/IR/Dominators.cpp<br>
> @@ -90,9 +90,10 @@ template void llvm::DomTreeBuilder::DeleteEdge<DomTreeBuilder::BBPostDomTree>(<br>
>      DomTreeBuilder::BBPostDomTree &DT, BasicBlock *From, BasicBlock *To);<br>
><br>
>  template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBDomTree>(<br>
> -    DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBUpdates);<br>
> +    DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBDomTreeGraphDiff &);<br>
>  template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBPostDomTree>(<br>
> -    DomTreeBuilder::BBPostDomTree &DT, DomTreeBuilder::BBUpdates);<br>
> +    DomTreeBuilder::BBPostDomTree &DT,<br>
> +    DomTreeBuilder::BBPostDomTreeGraphDiff &);<br>
><br>
>  template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBDomTree>(<br>
>      const DomTreeBuilder::BBDomTree &DT,<br>
><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank" rel="noreferrer">llvm-commits@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div>