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

Alina Sbirlea via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 14 14:01:04 PDT 2018


Hope rL339724 (D50734) fixed this.
Thank you for the heads up!

On Tue, Aug 14, 2018 at 11:25 AM Raphael Isemann <teemperor at gmail.com>
wrote:

> >+#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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180814/3ca0ed2e/attachment.html>


More information about the llvm-commits mailing list