[llvm] r339689 - Expose CFG Update struct. Define GraphTraits to get children given a snapshot CFG.

Raphael Isemann via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 14 11:24:36 PDT 2018


>+#include "llvm/IR/BasicBlock.h"
>+#include "llvm/IR/CFG.h"

These includes just broke the LLVM_ENABLE_MODULES build (at least it
will once the modules bot will be finished building, but it already
fails locally for me).

Anyone knows if this actually breaks the layering or if we just need
to restructure the modulemap? Don't know that code well enough.

> While building module 'LLVM_DebugInfo_PDB' imported from /Users/teemperor/llvm/thirdstuff/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp:10:
> While building module 'LLVM_DebugInfo' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/PDB/PDBContext.h:13:
> While building module 'LLVM_Object' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/DIContext.h:19:
> While building module 'LLVM_IR' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/Object/IRSymtab.h:30:
> While building module 'LLVM_intrinsic_gen' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/IR/CFGDiff.h:22:
> In file included from <module-includes>:1:
> /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/IR/Argument.h:20:10: fatal error: cyclic dependency in module 'LLVM_IR': LLVM_IR -> LLVM_intrinsic_gen -> LLVM_IR
> #include "llvm/IR/Value.h"
>          ^
> While building module 'LLVM_DebugInfo_PDB' imported from /Users/teemperor/llvm/thirdstuff/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp:10:
> While building module 'LLVM_DebugInfo' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/PDB/PDBContext.h:13:
> While building module 'LLVM_Object' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/DIContext.h:19:
> While building module 'LLVM_IR' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/Object/IRSymtab.h:30:
> In file included from <module-includes>:32:
> /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/IR/CFGDiff.h:22:10: fatal error: could not build module 'LLVM_intrinsic_gen'
> #include "llvm/IR/CFG.h"
>  ~~~~~~~~^~~~~~~~~~~~~~~

Am Di., 14. Aug. 2018 um 09:45 Uhr schrieb Alina Sbirlea via
llvm-commits <llvm-commits at lists.llvm.org>:
>
> Author: asbirlea
> Date: Tue Aug 14 09:44:28 2018
> New Revision: 339689
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339689&view=rev
> Log:
> Expose CFG Update struct. Define GraphTraits to get children given a snapshot CFG.
>
> Summary:
> Certain passes or analysis need to view a CFG snapshot rather than the actual CFG. This patch provides GraphTraits to offer such a view.
>
> The patch defines GraphTraits for BasicBlock* and Inverse<BasicBlock*> to provide CFG successors and predecessors based on a list of CFG updates.
>
> An Update is defined as a triple {InsertOrDeleteKind, BlockStartOfEdge, BlockEndOfEdge}.
> A GraphDiff is defined as a list of Updates that has been preprocessed to treat the CFG as a graph rather than a multi-graph. As such, there can only exist a single Update given two nodes. All duplicates will be filtered and Insert/Delete edges that cancel out will be ignored.
> The methods GraphDiff exposes are:
> - Determine if an existing child needs to be ignored, i.e. an Update exists in the correct direction to assume the removal of that edge.
> - Return a list of new children to be considered, i.e. an Update exists in the correct direction for each child in the list to assume the insertion of that edge.
>
> Reviewers: timshen, kuhar, chandlerc
>
> Subscribers: sanjoy, jlebar, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D50479
>
> Added:
>     llvm/trunk/include/llvm/IR/CFGDiff.h
>     llvm/trunk/include/llvm/Support/CFGUpdate.h
> Modified:
>     llvm/trunk/include/llvm/ADT/iterator.h
>
> Modified: llvm/trunk/include/llvm/ADT/iterator.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/iterator.h?rev=339689&r1=339688&r2=339689&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/iterator.h (original)
> +++ llvm/trunk/include/llvm/ADT/iterator.h Tue Aug 14 09:44:28 2018
> @@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) {
>                      PointerIteratorT(std::end(std::forward<RangeT>(Range))));
>  }
>
> +// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,
> +// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>.
> +template <typename ItType, typename NodeRef, typename DataRef>
> +class WrappedPairNodeDataIterator
> +    : public iterator_adaptor_base<
> +          WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType,
> +          typename std::iterator_traits<ItType>::iterator_category, NodeRef,
> +          std::ptrdiff_t, NodeRef *, NodeRef &> {
> +  using BaseT = iterator_adaptor_base<
> +      WrappedPairNodeDataIterator, ItType,
> +      typename std::iterator_traits<ItType>::iterator_category, NodeRef,
> +      std::ptrdiff_t, NodeRef *, NodeRef &>;
> +
> +  const DataRef DR;
> +  mutable NodeRef NR;
> +
> +public:
> +  WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)
> +      : BaseT(Begin), DR(DR) {
> +    NR.first = DR;
> +  }
> +
> +  NodeRef &operator*() const {
> +    NR.second = *this->I;
> +    return NR;
> +  }
> +};
> +
>  } // end namespace llvm
>
>  #endif // LLVM_ADT_ITERATOR_H
>
> Added: llvm/trunk/include/llvm/IR/CFGDiff.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CFGDiff.h?rev=339689&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/CFGDiff.h (added)
> +++ llvm/trunk/include/llvm/IR/CFGDiff.h Tue Aug 14 09:44:28 2018
> @@ -0,0 +1,286 @@
> +//===- CFGDiff.h - Define a CFG snapshot. -----------------------*- 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 specializations of GraphTraits that allows generic
> +// algorithms to see a different snapshot of a CFG.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_IR_CFGDIFF_H
> +#define LLVM_IR_CFGDIFF_H
> +
> +#include "llvm/ADT/GraphTraits.h"
> +#include "llvm/ADT/iterator.h"
> +#include "llvm/ADT/iterator_range.h"
> +#include "llvm/IR/BasicBlock.h"
> +#include "llvm/IR/CFG.h"
> +#include "llvm/Support/CFGUpdate.h"
> +#include "llvm/Support/type_traits.h"
> +#include <cassert>
> +#include <cstddef>
> +#include <iterator>
> +
> +// Two booleans are used to define orders in graphs:
> +// InverseGraph defines when we need to reverse the whole graph and is as such
> +// also equivalent to applying updates in reverse.
> +// InverseEdge defines whether we want to change the edges direction. E.g., for
> +// a non-inversed graph, the children are naturally the successors when
> +// InverseEdge is false and the predecessors when InverseEdge is true.
> +
> +// We define two base clases that call into GraphDiff, one for successors
> +// (CFGSuccessors), where InverseEdge is false, and one for predecessors
> +// (CFGPredecessors), where InverseEdge is true.
> +// FIXME: Further refactoring may merge the two base classes into a single one
> +// templated / parametrized on using succ_iterator/pred_iterator and false/true
> +// for the InverseEdge.
> +
> +// CFGViewSuccessors and CFGViewPredecessors, both can be parametrized to
> +// consider the graph inverted or not (i.e. InverseGraph). Successors
> +// implicitly has InverseEdge = false and Predecessors implicitly has
> +// InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits
> +// instantiations that follow define the value of InverseGraph.
> +
> +// GraphTraits instantiations:
> +// - GraphDiff<BasicBlock *> is equivalent to InverseGraph = false
> +// - GraphDiff<Inverse<BasicBlock *>> is equivalent to InverseGraph = true
> +// - second pair item is BasicBlock *, then InverseEdge = false (so it inherits
> +// from CFGViewSuccessors).
> +// - second pair item is Inverse<BasicBlock *>, then InverseEdge = true (so it
> +// inherits from CFGViewPredecessors).
> +
> +// The 4 GraphTraits are as follows:
> +// 1. std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>> :
> +//        CFGViewSuccessors<false>
> +// Regular CFG, children means successors, InverseGraph = false,
> +// InverseEdge = false.
> +// 2. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>> :
> +//        CFGViewSuccessors<true>
> +// Reverse the graph, get successors but reverse-apply updates,
> +// InverseGraph = true, InverseEdge = false.
> +// 3. std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>> :
> +//        CFGViewPredecessors<false>
> +// Regular CFG, reverse edges, so children mean predecessors,
> +// InverseGraph = false, InverseEdge = true.
> +// 4. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>>
> +//        : CFGViewPredecessors<true>
> +// Reverse the graph and the edges, InverseGraph = true, InverseEdge = true.
> +
> +namespace llvm {
> +
> +// GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provide
> +// utilities to skip edges marked as deleted and return a set of edges marked as
> +// newly inserted. The current diff treats the CFG as a graph rather than a
> +// multigraph. Added edges are pruned to be unique, and deleted edges will
> +// remove all existing edges between two blocks.
> +template <typename NodePtr> class GraphDiff {
> +  using UpdateMapType = SmallDenseMap<NodePtr, SmallVector<NodePtr, 2>>;
> +  UpdateMapType SuccInsert;
> +  UpdateMapType SuccDelete;
> +  UpdateMapType PredInsert;
> +  UpdateMapType PredDelete;
> +  // Using a singleton empty vector for all BasicBlock requests with no
> +  // children.
> +  SmallVector<NodePtr, 1> Empty;
> +
> +  void printMap(raw_ostream &OS, const UpdateMapType &M) const {
> +    for (auto Pair : M)
> +      for (auto Child : Pair.second) {
> +        OS << "(";
> +        Pair.first->printAsOperand(OS, false);
> +        OS << ", ";
> +        Child->printAsOperand(OS, false);
> +        OS << ") ";
> +      }
> +    OS << "\n";
> +  }
> +
> +public:
> +  GraphDiff() {}
> +  GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates, bool InverseGraph = false) {
> +    SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
> +    cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
> +    for (auto U : LegalizedUpdates) {
> +      if (U.getKind() == cfg::UpdateKind::Insert) {
> +        SuccInsert[U.getFrom()].push_back(U.getTo());
> +        PredInsert[U.getTo()].push_back(U.getFrom());
> +      } else {
> +        SuccDelete[U.getFrom()].push_back(U.getTo());
> +        PredDelete[U.getTo()].push_back(U.getFrom());
> +      }
> +    }
> +  }
> +
> +  bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge,
> +                   bool InverseGraph) const {
> +    auto &DeleteChildren =
> +        (InverseEdge != InverseGraph) ? PredDelete : SuccDelete;
> +    auto It = DeleteChildren.find(BB);
> +    if (It == DeleteChildren.end())
> +      return false;
> +    auto &EdgesForBB = It->second;
> +    return llvm::find(EdgesForBB, EdgeEnd) != EdgesForBB.end();
> +  }
> +
> +  iterator_range<typename SmallVectorImpl<NodePtr>::const_iterator>
> +  getAddedChildren(const NodePtr BB, bool InverseEdge,
> +                   bool InverseGraph) const {
> +    auto &InsertChildren =
> +        (InverseEdge != InverseGraph) ? PredInsert : SuccInsert;
> +    auto It = InsertChildren.find(BB);
> +    if (It == InsertChildren.end())
> +      return make_range(Empty.begin(), Empty.end());
> +    return make_range(It->second.begin(), It->second.end());
> +  }
> +
> +  void print(raw_ostream &OS) const {
> +    OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
> +          "===== (Note: notion of children/inverse_children depends on "
> +          "the direction of edges and the graph.)\n";
> +    OS << "Children to insert:\n\t";
> +    printMap(OS, SuccInsert);
> +    OS << "Children to delete:\n\t";
> +    printMap(OS, SuccDelete);
> +    OS << "Inverse_children to insert:\n\t";
> +    printMap(OS, PredInsert);
> +    OS << "Inverse_children to delete:\n\t";
> +    printMap(OS, PredDelete);
> +    OS << "\n";
> +  }
> +
> +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
> +  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
> +#endif
> +};
> +
> +template <bool InverseGraph = false> struct CFGViewSuccessors {
> +  using DataRef = const GraphDiff<BasicBlock *> *;
> +  using NodeRef = std::pair<DataRef, BasicBlock *>;
> +
> +  using ExistingChildIterator =
> +      WrappedPairNodeDataIterator<succ_iterator, NodeRef, DataRef>;
> +  struct DeletedEdgesFilter {
> +    BasicBlock *BB;
> +    DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};
> +    bool operator()(NodeRef N) const {
> +      return !N.first->ignoreChild(BB, N.second, false, InverseGraph);
> +    }
> +  };
> +  using FilterExistingChildrenIterator =
> +      filter_iterator<ExistingChildIterator, DeletedEdgesFilter>;
> +
> +  using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator;
> +  using AddNewChildrenIterator =
> +      WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>;
> +  using ChildIteratorType =
> +      concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                      AddNewChildrenIterator>;
> +
> +  static ChildIteratorType child_begin(NodeRef N) {
> +    auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);
> +    // filter iterator init:
> +    auto firstit = make_filter_range(
> +        make_range<ExistingChildIterator>({succ_begin(N.second), N.first},
> +                                          {succ_end(N.second), N.first}),
> +        DeletedEdgesFilter(N.second));
> +    // new inserts iterator init:
> +    auto secondit = make_range<AddNewChildrenIterator>(
> +        {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
> +
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                           AddNewChildrenIterator>(firstit, secondit);
> +  }
> +
> +  static ChildIteratorType child_end(NodeRef N) {
> +    auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);
> +    // filter iterator init:
> +    auto firstit = make_filter_range(
> +        make_range<ExistingChildIterator>({succ_end(N.second), N.first},
> +                                          {succ_end(N.second), N.first}),
> +        DeletedEdgesFilter(N.second));
> +    // new inserts iterator init:
> +    auto secondit = make_range<AddNewChildrenIterator>(
> +        {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
> +
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                           AddNewChildrenIterator>(firstit, secondit);
> +  }
> +};
> +
> +template <bool InverseGraph = false> struct CFGViewPredecessors {
> +  using DataRef = const GraphDiff<BasicBlock *> *;
> +  using NodeRef = std::pair<DataRef, BasicBlock *>;
> +
> +  using ExistingChildIterator =
> +      WrappedPairNodeDataIterator<pred_iterator, NodeRef, DataRef>;
> +  struct DeletedEdgesFilter {
> +    BasicBlock *BB;
> +    DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};
> +    bool operator()(NodeRef N) const {
> +      return !N.first->ignoreChild(BB, N.second, true, InverseGraph);
> +    }
> +  };
> +  using FilterExistingChildrenIterator =
> +      filter_iterator<ExistingChildIterator, DeletedEdgesFilter>;
> +
> +  using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator;
> +  using AddNewChildrenIterator =
> +      WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>;
> +  using ChildIteratorType =
> +      concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                      AddNewChildrenIterator>;
> +
> +  static ChildIteratorType child_begin(NodeRef N) {
> +    auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);
> +    // filter iterator init:
> +    auto firstit = make_filter_range(
> +        make_range<ExistingChildIterator>({pred_begin(N.second), N.first},
> +                                          {pred_end(N.second), N.first}),
> +        DeletedEdgesFilter(N.second));
> +    // new inserts iterator init:
> +    auto secondit = make_range<AddNewChildrenIterator>(
> +        {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
> +
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                           AddNewChildrenIterator>(firstit, secondit);
> +  }
> +
> +  static ChildIteratorType child_end(NodeRef N) {
> +    auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);
> +    // filter iterator init:
> +    auto firstit = make_filter_range(
> +        make_range<ExistingChildIterator>({pred_end(N.second), N.first},
> +                                          {pred_end(N.second), N.first}),
> +        DeletedEdgesFilter(N.second));
> +    // new inserts iterator init:
> +    auto secondit = make_range<AddNewChildrenIterator>(
> +        {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
> +
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,
> +                           AddNewChildrenIterator>(firstit, secondit);
> +  }
> +};
> +
> +template <>
> +struct GraphTraits<std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>>
> +    : CFGViewSuccessors<false> {};
> +template <>
> +struct GraphTraits<
> +    std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>>
> +    : CFGViewSuccessors<true> {};
> +template <>
> +struct GraphTraits<
> +    std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>>
> +    : CFGViewPredecessors<false> {};
> +template <>
> +struct GraphTraits<
> +    std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>>>
> +    : CFGViewPredecessors<true> {};
> +} // end namespace llvm
> +
> +#endif // LLVM_IR_CFGDIFF_H
>
> Added: llvm/trunk/include/llvm/Support/CFGUpdate.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CFGUpdate.h?rev=339689&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/CFGUpdate.h (added)
> +++ llvm/trunk/include/llvm/Support/CFGUpdate.h Tue Aug 14 09:44:28 2018
> @@ -0,0 +1,113 @@
> +//===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- 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 a CFG Edge Update: Insert or Delete, and two Nodes as the
> +// Edge ends.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_CFGUPDATE_H
> +#define LLVM_SUPPORT_CFGUPDATE_H
> +
> +#include "llvm/Support/Debug.h"
> +
> +namespace llvm {
> +namespace cfg {
> +enum class UpdateKind : unsigned char { Insert, Delete };
> +
> +template <typename NodePtr> class Update {
> +  using NodeKindPair = PointerIntPair<NodePtr, 1, UpdateKind>;
> +  NodePtr From;
> +  NodeKindPair ToAndKind;
> +
> +public:
> +  Update(UpdateKind Kind, NodePtr From, NodePtr To)
> +      : From(From), ToAndKind(To, Kind) {}
> +
> +  UpdateKind getKind() const { return ToAndKind.getInt(); }
> +  NodePtr getFrom() const { return From; }
> +  NodePtr getTo() const { return ToAndKind.getPointer(); }
> +  bool operator==(const Update &RHS) const {
> +    return From == RHS.From && ToAndKind == RHS.ToAndKind;
> +  }
> +
> +  void print(raw_ostream &OS) const {
> +    OS << (getKind() == UpdateKind::Insert ? "Insert " : "Delete ");
> +    getFrom()->printAsOperand(OS, false);
> +    OS << " -> ";
> +    getTo()->printAsOperand(OS, false);
> +  }
> +
> +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
> +  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
> +#endif
> +};
> +
> +// LegalizeUpdates function simplifies updates assuming a graph structure.
> +// This function serves double purpose:
> +// a) It removes redundant updates, which makes it easier to reverse-apply
> +//    them when traversing CFG.
> +// b) It optimizes away updates that cancel each other out, as the end result
> +//    is the same.
> +template <typename NodePtr>
> +void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
> +                     SmallVectorImpl<Update<NodePtr>> &Result,
> +                     bool InverseGraph) {
> +  // Count the total number of inserions of each edge.
> +  // Each insertion adds 1 and deletion subtracts 1. The end number should be
> +  // one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
> +  // of updates contains multiple updates of the same kind and we assert for
> +  // that case.
> +  SmallDenseMap<std::pair<NodePtr, NodePtr>, int, 4> Operations;
> +  Operations.reserve(AllUpdates.size());
> +
> +  for (const auto &U : AllUpdates) {
> +    NodePtr From = U.getFrom();
> +    NodePtr To = U.getTo();
> +    if (InverseGraph)
> +      std::swap(From, To); // Reverse edge for postdominators.
> +
> +    Operations[{From, To}] += (U.getKind() == UpdateKind::Insert ? 1 : -1);
> +  }
> +
> +  Result.clear();
> +  Result.reserve(Operations.size());
> +  for (auto &Op : Operations) {
> +    const int NumInsertions = Op.second;
> +    assert(std::abs(NumInsertions) <= 1 && "Unbalanced operations!");
> +    if (NumInsertions == 0)
> +      continue;
> +    const UpdateKind UK =
> +        NumInsertions > 0 ? UpdateKind::Insert : UpdateKind::Delete;
> +    Result.push_back({UK, Op.first.first, Op.first.second});
> +  }
> +
> +  // Make the order consistent by not relying on pointer values within the
> +  // set. Reuse the old Operations map.
> +  // In the future, we should sort by something else to minimize the amount
> +  // of work needed to perform the series of updates.
> +  for (size_t i = 0, e = AllUpdates.size(); i != e; ++i) {
> +    const auto &U = AllUpdates[i];
> +    if (!InverseGraph)
> +      Operations[{U.getFrom(), U.getTo()}] = int(i);
> +    else
> +      Operations[{U.getTo(), U.getFrom()}] = int(i);
> +  }
> +
> +  llvm::sort(Result.begin(), Result.end(),
> +             [&Operations](const Update<NodePtr> &A, const Update<NodePtr> &B) {
> +               return Operations[{A.getFrom(), A.getTo()}] >
> +                      Operations[{B.getFrom(), B.getTo()}];
> +             });
> +}
> +
> +} // end namespace cfg
> +} // end namespace llvm
> +
> +#endif // LLVM_SUPPORT_CFGUPDATE_H
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list