<div dir="ltr">Hope <span style="font-family:arial,sans-serif;font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">rL339724 (D50734) fixed this.</span><div><span style="font-family:arial,sans-serif;font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Thank you for the heads up!</span></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Aug 14, 2018 at 11:25 AM Raphael Isemann <<a href="mailto:teemperor@gmail.com">teemperor@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>+#include "llvm/IR/BasicBlock.h"<br>
>+#include "llvm/IR/CFG.h"<br>
<br>
These includes just broke the LLVM_ENABLE_MODULES build (at least it<br>
will once the modules bot will be finished building, but it already<br>
fails locally for me).<br>
<br>
Anyone knows if this actually breaks the layering or if we just need<br>
to restructure the modulemap? Don't know that code well enough.<br>
<br>
> While building module 'LLVM_DebugInfo_PDB' imported from /Users/teemperor/llvm/thirdstuff/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp:10:<br>
> While building module 'LLVM_DebugInfo' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/PDB/PDBContext.h:13:<br>
> While building module 'LLVM_Object' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/DIContext.h:19:<br>
> While building module 'LLVM_IR' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/Object/IRSymtab.h:30:<br>
> While building module 'LLVM_intrinsic_gen' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/IR/CFGDiff.h:22:<br>
> In file included from <module-includes>:1:<br>
> /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<br>
> #include "llvm/IR/Value.h"<br>
>          ^<br>
> While building module 'LLVM_DebugInfo_PDB' imported from /Users/teemperor/llvm/thirdstuff/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp:10:<br>
> While building module 'LLVM_DebugInfo' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/PDB/PDBContext.h:13:<br>
> While building module 'LLVM_Object' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/DebugInfo/DIContext.h:19:<br>
> While building module 'LLVM_IR' imported from /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/Object/IRSymtab.h:30:<br>
> In file included from <module-includes>:32:<br>
> /Users/teemperor/llvm/thirdstuff/llvm/include/llvm/IR/CFGDiff.h:22:10: fatal error: could not build module 'LLVM_intrinsic_gen'<br>
> #include "llvm/IR/CFG.h"<br>
>  ~~~~~~~~^~~~~~~~~~~~~~~<br>
<br>
Am Di., 14. Aug. 2018 um 09:45 Uhr schrieb Alina Sbirlea via<br>
llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>>:<br>
><br>
> Author: asbirlea<br>
> Date: Tue Aug 14 09:44:28 2018<br>
> New Revision: 339689<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=339689&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=339689&view=rev</a><br>
> Log:<br>
> Expose CFG Update struct. Define GraphTraits to get children given a snapshot CFG.<br>
><br>
> Summary:<br>
> Certain passes or analysis need to view a CFG snapshot rather than the actual CFG. This patch provides GraphTraits to offer such a view.<br>
><br>
> The patch defines GraphTraits for BasicBlock* and Inverse<BasicBlock*> to provide CFG successors and predecessors based on a list of CFG updates.<br>
><br>
> An Update is defined as a triple {InsertOrDeleteKind, BlockStartOfEdge, BlockEndOfEdge}.<br>
> 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.<br>
> The methods GraphDiff exposes are:<br>
> - 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.<br>
> - 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.<br>
><br>
> Reviewers: timshen, kuhar, chandlerc<br>
><br>
> Subscribers: sanjoy, jlebar, llvm-commits<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D50479" rel="noreferrer" target="_blank">https://reviews.llvm.org/D50479</a><br>
><br>
> Added:<br>
>     llvm/trunk/include/llvm/IR/CFGDiff.h<br>
>     llvm/trunk/include/llvm/Support/CFGUpdate.h<br>
> Modified:<br>
>     llvm/trunk/include/llvm/ADT/iterator.h<br>
><br>
> Modified: llvm/trunk/include/llvm/ADT/iterator.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/iterator.h?rev=339689&r1=339688&r2=339689&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/iterator.h?rev=339689&r1=339688&r2=339689&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/ADT/iterator.h (original)<br>
> +++ llvm/trunk/include/llvm/ADT/iterator.h Tue Aug 14 09:44:28 2018<br>
> @@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) {<br>
>                      PointerIteratorT(std::end(std::forward<RangeT>(Range))));<br>
>  }<br>
><br>
> +// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,<br>
> +// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>.<br>
> +template <typename ItType, typename NodeRef, typename DataRef><br>
> +class WrappedPairNodeDataIterator<br>
> +    : public iterator_adaptor_base<<br>
> +          WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType,<br>
> +          typename std::iterator_traits<ItType>::iterator_category, NodeRef,<br>
> +          std::ptrdiff_t, NodeRef *, NodeRef &> {<br>
> +  using BaseT = iterator_adaptor_base<<br>
> +      WrappedPairNodeDataIterator, ItType,<br>
> +      typename std::iterator_traits<ItType>::iterator_category, NodeRef,<br>
> +      std::ptrdiff_t, NodeRef *, NodeRef &>;<br>
> +<br>
> +  const DataRef DR;<br>
> +  mutable NodeRef NR;<br>
> +<br>
> +public:<br>
> +  WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)<br>
> +      : BaseT(Begin), DR(DR) {<br>
> +    NR.first = DR;<br>
> +  }<br>
> +<br>
> +  NodeRef &operator*() const {<br>
> +    NR.second = *this->I;<br>
> +    return NR;<br>
> +  }<br>
> +};<br>
> +<br>
>  } // end namespace llvm<br>
><br>
>  #endif // LLVM_ADT_ITERATOR_H<br>
><br>
> Added: llvm/trunk/include/llvm/IR/CFGDiff.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CFGDiff.h?rev=339689&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CFGDiff.h?rev=339689&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/IR/CFGDiff.h (added)<br>
> +++ llvm/trunk/include/llvm/IR/CFGDiff.h Tue Aug 14 09:44:28 2018<br>
> @@ -0,0 +1,286 @@<br>
> +//===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file defines specializations of GraphTraits that allows generic<br>
> +// algorithms to see a different snapshot of a CFG.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_IR_CFGDIFF_H<br>
> +#define LLVM_IR_CFGDIFF_H<br>
> +<br>
> +#include "llvm/ADT/GraphTraits.h"<br>
> +#include "llvm/ADT/iterator.h"<br>
> +#include "llvm/ADT/iterator_range.h"<br>
> +#include "llvm/IR/BasicBlock.h"<br>
> +#include "llvm/IR/CFG.h"<br>
> +#include "llvm/Support/CFGUpdate.h"<br>
> +#include "llvm/Support/type_traits.h"<br>
> +#include <cassert><br>
> +#include <cstddef><br>
> +#include <iterator><br>
> +<br>
> +// Two booleans are used to define orders in graphs:<br>
> +// InverseGraph defines when we need to reverse the whole graph and is as such<br>
> +// also equivalent to applying updates in reverse.<br>
> +// InverseEdge defines whether we want to change the edges direction. E.g., for<br>
> +// a non-inversed graph, the children are naturally the successors when<br>
> +// InverseEdge is false and the predecessors when InverseEdge is true.<br>
> +<br>
> +// We define two base clases that call into GraphDiff, one for successors<br>
> +// (CFGSuccessors), where InverseEdge is false, and one for predecessors<br>
> +// (CFGPredecessors), where InverseEdge is true.<br>
> +// FIXME: Further refactoring may merge the two base classes into a single one<br>
> +// templated / parametrized on using succ_iterator/pred_iterator and false/true<br>
> +// for the InverseEdge.<br>
> +<br>
> +// CFGViewSuccessors and CFGViewPredecessors, both can be parametrized to<br>
> +// consider the graph inverted or not (i.e. InverseGraph). Successors<br>
> +// implicitly has InverseEdge = false and Predecessors implicitly has<br>
> +// InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits<br>
> +// instantiations that follow define the value of InverseGraph.<br>
> +<br>
> +// GraphTraits instantiations:<br>
> +// - GraphDiff<BasicBlock *> is equivalent to InverseGraph = false<br>
> +// - GraphDiff<Inverse<BasicBlock *>> is equivalent to InverseGraph = true<br>
> +// - second pair item is BasicBlock *, then InverseEdge = false (so it inherits<br>
> +// from CFGViewSuccessors).<br>
> +// - second pair item is Inverse<BasicBlock *>, then InverseEdge = true (so it<br>
> +// inherits from CFGViewPredecessors).<br>
> +<br>
> +// The 4 GraphTraits are as follows:<br>
> +// 1. std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>> :<br>
> +//        CFGViewSuccessors<false><br>
> +// Regular CFG, children means successors, InverseGraph = false,<br>
> +// InverseEdge = false.<br>
> +// 2. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>> :<br>
> +//        CFGViewSuccessors<true><br>
> +// Reverse the graph, get successors but reverse-apply updates,<br>
> +// InverseGraph = true, InverseEdge = false.<br>
> +// 3. std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>> :<br>
> +//        CFGViewPredecessors<false><br>
> +// Regular CFG, reverse edges, so children mean predecessors,<br>
> +// InverseGraph = false, InverseEdge = true.<br>
> +// 4. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>><br>
> +//        : CFGViewPredecessors<true><br>
> +// Reverse the graph and the edges, InverseGraph = true, InverseEdge = true.<br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +// GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provide<br>
> +// utilities to skip edges marked as deleted and return a set of edges marked as<br>
> +// newly inserted. The current diff treats the CFG as a graph rather than a<br>
> +// multigraph. Added edges are pruned to be unique, and deleted edges will<br>
> +// remove all existing edges between two blocks.<br>
> +template <typename NodePtr> class GraphDiff {<br>
> +  using UpdateMapType = SmallDenseMap<NodePtr, SmallVector<NodePtr, 2>>;<br>
> +  UpdateMapType SuccInsert;<br>
> +  UpdateMapType SuccDelete;<br>
> +  UpdateMapType PredInsert;<br>
> +  UpdateMapType PredDelete;<br>
> +  // Using a singleton empty vector for all BasicBlock requests with no<br>
> +  // children.<br>
> +  SmallVector<NodePtr, 1> Empty;<br>
> +<br>
> +  void printMap(raw_ostream &OS, const UpdateMapType &M) const {<br>
> +    for (auto Pair : M)<br>
> +      for (auto Child : Pair.second) {<br>
> +        OS << "(";<br>
> +        Pair.first->printAsOperand(OS, false);<br>
> +        OS << ", ";<br>
> +        Child->printAsOperand(OS, false);<br>
> +        OS << ") ";<br>
> +      }<br>
> +    OS << "\n";<br>
> +  }<br>
> +<br>
> +public:<br>
> +  GraphDiff() {}<br>
> +  GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates, bool InverseGraph = false) {<br>
> +    SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;<br>
> +    cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);<br>
> +    for (auto U : LegalizedUpdates) {<br>
> +      if (U.getKind() == cfg::UpdateKind::Insert) {<br>
> +        SuccInsert[U.getFrom()].push_back(U.getTo());<br>
> +        PredInsert[U.getTo()].push_back(U.getFrom());<br>
> +      } else {<br>
> +        SuccDelete[U.getFrom()].push_back(U.getTo());<br>
> +        PredDelete[U.getTo()].push_back(U.getFrom());<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +<br>
> +  bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge,<br>
> +                   bool InverseGraph) const {<br>
> +    auto &DeleteChildren =<br>
> +        (InverseEdge != InverseGraph) ? PredDelete : SuccDelete;<br>
> +    auto It = DeleteChildren.find(BB);<br>
> +    if (It == DeleteChildren.end())<br>
> +      return false;<br>
> +    auto &EdgesForBB = It->second;<br>
> +    return llvm::find(EdgesForBB, EdgeEnd) != EdgesForBB.end();<br>
> +  }<br>
> +<br>
> +  iterator_range<typename SmallVectorImpl<NodePtr>::const_iterator><br>
> +  getAddedChildren(const NodePtr BB, bool InverseEdge,<br>
> +                   bool InverseGraph) const {<br>
> +    auto &InsertChildren =<br>
> +        (InverseEdge != InverseGraph) ? PredInsert : SuccInsert;<br>
> +    auto It = InsertChildren.find(BB);<br>
> +    if (It == InsertChildren.end())<br>
> +      return make_range(Empty.begin(), Empty.end());<br>
> +    return make_range(It->second.begin(), It->second.end());<br>
> +  }<br>
> +<br>
> +  void print(raw_ostream &OS) const {<br>
> +    OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"<br>
> +          "===== (Note: notion of children/inverse_children depends on "<br>
> +          "the direction of edges and the graph.)\n";<br>
> +    OS << "Children to insert:\n\t";<br>
> +    printMap(OS, SuccInsert);<br>
> +    OS << "Children to delete:\n\t";<br>
> +    printMap(OS, SuccDelete);<br>
> +    OS << "Inverse_children to insert:\n\t";<br>
> +    printMap(OS, PredInsert);<br>
> +    OS << "Inverse_children to delete:\n\t";<br>
> +    printMap(OS, PredDelete);<br>
> +    OS << "\n";<br>
> +  }<br>
> +<br>
> +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)<br>
> +  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }<br>
> +#endif<br>
> +};<br>
> +<br>
> +template <bool InverseGraph = false> struct CFGViewSuccessors {<br>
> +  using DataRef = const GraphDiff<BasicBlock *> *;<br>
> +  using NodeRef = std::pair<DataRef, BasicBlock *>;<br>
> +<br>
> +  using ExistingChildIterator =<br>
> +      WrappedPairNodeDataIterator<succ_iterator, NodeRef, DataRef>;<br>
> +  struct DeletedEdgesFilter {<br>
> +    BasicBlock *BB;<br>
> +    DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};<br>
> +    bool operator()(NodeRef N) const {<br>
> +      return !N.first->ignoreChild(BB, N.second, false, InverseGraph);<br>
> +    }<br>
> +  };<br>
> +  using FilterExistingChildrenIterator =<br>
> +      filter_iterator<ExistingChildIterator, DeletedEdgesFilter>;<br>
> +<br>
> +  using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator;<br>
> +  using AddNewChildrenIterator =<br>
> +      WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>;<br>
> +  using ChildIteratorType =<br>
> +      concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                      AddNewChildrenIterator>;<br>
> +<br>
> +  static ChildIteratorType child_begin(NodeRef N) {<br>
> +    auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);<br>
> +    // filter iterator init:<br>
> +    auto firstit = make_filter_range(<br>
> +        make_range<ExistingChildIterator>({succ_begin(N.second), N.first},<br>
> +                                          {succ_end(N.second), N.first}),<br>
> +        DeletedEdgesFilter(N.second));<br>
> +    // new inserts iterator init:<br>
> +    auto secondit = make_range<AddNewChildrenIterator>(<br>
> +        {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});<br>
> +<br>
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                           AddNewChildrenIterator>(firstit, secondit);<br>
> +  }<br>
> +<br>
> +  static ChildIteratorType child_end(NodeRef N) {<br>
> +    auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);<br>
> +    // filter iterator init:<br>
> +    auto firstit = make_filter_range(<br>
> +        make_range<ExistingChildIterator>({succ_end(N.second), N.first},<br>
> +                                          {succ_end(N.second), N.first}),<br>
> +        DeletedEdgesFilter(N.second));<br>
> +    // new inserts iterator init:<br>
> +    auto secondit = make_range<AddNewChildrenIterator>(<br>
> +        {InsertVec.end(), N.first}, {InsertVec.end(), N.first});<br>
> +<br>
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                           AddNewChildrenIterator>(firstit, secondit);<br>
> +  }<br>
> +};<br>
> +<br>
> +template <bool InverseGraph = false> struct CFGViewPredecessors {<br>
> +  using DataRef = const GraphDiff<BasicBlock *> *;<br>
> +  using NodeRef = std::pair<DataRef, BasicBlock *>;<br>
> +<br>
> +  using ExistingChildIterator =<br>
> +      WrappedPairNodeDataIterator<pred_iterator, NodeRef, DataRef>;<br>
> +  struct DeletedEdgesFilter {<br>
> +    BasicBlock *BB;<br>
> +    DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};<br>
> +    bool operator()(NodeRef N) const {<br>
> +      return !N.first->ignoreChild(BB, N.second, true, InverseGraph);<br>
> +    }<br>
> +  };<br>
> +  using FilterExistingChildrenIterator =<br>
> +      filter_iterator<ExistingChildIterator, DeletedEdgesFilter>;<br>
> +<br>
> +  using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator;<br>
> +  using AddNewChildrenIterator =<br>
> +      WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>;<br>
> +  using ChildIteratorType =<br>
> +      concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                      AddNewChildrenIterator>;<br>
> +<br>
> +  static ChildIteratorType child_begin(NodeRef N) {<br>
> +    auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);<br>
> +    // filter iterator init:<br>
> +    auto firstit = make_filter_range(<br>
> +        make_range<ExistingChildIterator>({pred_begin(N.second), N.first},<br>
> +                                          {pred_end(N.second), N.first}),<br>
> +        DeletedEdgesFilter(N.second));<br>
> +    // new inserts iterator init:<br>
> +    auto secondit = make_range<AddNewChildrenIterator>(<br>
> +        {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});<br>
> +<br>
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                           AddNewChildrenIterator>(firstit, secondit);<br>
> +  }<br>
> +<br>
> +  static ChildIteratorType child_end(NodeRef N) {<br>
> +    auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);<br>
> +    // filter iterator init:<br>
> +    auto firstit = make_filter_range(<br>
> +        make_range<ExistingChildIterator>({pred_end(N.second), N.first},<br>
> +                                          {pred_end(N.second), N.first}),<br>
> +        DeletedEdgesFilter(N.second));<br>
> +    // new inserts iterator init:<br>
> +    auto secondit = make_range<AddNewChildrenIterator>(<br>
> +        {InsertVec.end(), N.first}, {InsertVec.end(), N.first});<br>
> +<br>
> +    return concat_iterator<NodeRef, FilterExistingChildrenIterator,<br>
> +                           AddNewChildrenIterator>(firstit, secondit);<br>
> +  }<br>
> +};<br>
> +<br>
> +template <><br>
> +struct GraphTraits<std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>><br>
> +    : CFGViewSuccessors<false> {};<br>
> +template <><br>
> +struct GraphTraits<<br>
> +    std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>><br>
> +    : CFGViewSuccessors<true> {};<br>
> +template <><br>
> +struct GraphTraits<<br>
> +    std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>><br>
> +    : CFGViewPredecessors<false> {};<br>
> +template <><br>
> +struct GraphTraits<<br>
> +    std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>>><br>
> +    : CFGViewPredecessors<true> {};<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_IR_CFGDIFF_H<br>
><br>
> Added: llvm/trunk/include/llvm/Support/CFGUpdate.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CFGUpdate.h?rev=339689&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CFGUpdate.h?rev=339689&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Support/CFGUpdate.h (added)<br>
> +++ llvm/trunk/include/llvm/Support/CFGUpdate.h Tue Aug 14 09:44:28 2018<br>
> @@ -0,0 +1,113 @@<br>
> +//===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file defines a CFG Edge Update: Insert or Delete, and two Nodes as the<br>
> +// Edge ends.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_SUPPORT_CFGUPDATE_H<br>
> +#define LLVM_SUPPORT_CFGUPDATE_H<br>
> +<br>
> +#include "llvm/Support/Debug.h"<br>
> +<br>
> +namespace llvm {<br>
> +namespace cfg {<br>
> +enum class UpdateKind : unsigned char { Insert, Delete };<br>
> +<br>
> +template <typename NodePtr> class Update {<br>
> +  using NodeKindPair = PointerIntPair<NodePtr, 1, UpdateKind>;<br>
> +  NodePtr From;<br>
> +  NodeKindPair ToAndKind;<br>
> +<br>
> +public:<br>
> +  Update(UpdateKind Kind, NodePtr From, NodePtr To)<br>
> +      : From(From), ToAndKind(To, Kind) {}<br>
> +<br>
> +  UpdateKind getKind() const { return ToAndKind.getInt(); }<br>
> +  NodePtr getFrom() const { return From; }<br>
> +  NodePtr getTo() const { return ToAndKind.getPointer(); }<br>
> +  bool operator==(const Update &RHS) const {<br>
> +    return From == RHS.From && ToAndKind == RHS.ToAndKind;<br>
> +  }<br>
> +<br>
> +  void print(raw_ostream &OS) const {<br>
> +    OS << (getKind() == UpdateKind::Insert ? "Insert " : "Delete ");<br>
> +    getFrom()->printAsOperand(OS, false);<br>
> +    OS << " -> ";<br>
> +    getTo()->printAsOperand(OS, false);<br>
> +  }<br>
> +<br>
> +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)<br>
> +  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }<br>
> +#endif<br>
> +};<br>
> +<br>
> +// LegalizeUpdates function simplifies updates assuming a graph structure.<br>
> +// This function serves double purpose:<br>
> +// a) It removes redundant updates, which makes it easier to reverse-apply<br>
> +//    them when traversing CFG.<br>
> +// b) It optimizes away updates that cancel each other out, as the end result<br>
> +//    is the same.<br>
> +template <typename NodePtr><br>
> +void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,<br>
> +                     SmallVectorImpl<Update<NodePtr>> &Result,<br>
> +                     bool InverseGraph) {<br>
> +  // Count the total number of inserions of each edge.<br>
> +  // Each insertion adds 1 and deletion subtracts 1. The end number should be<br>
> +  // one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence<br>
> +  // of updates contains multiple updates of the same kind and we assert for<br>
> +  // that case.<br>
> +  SmallDenseMap<std::pair<NodePtr, NodePtr>, int, 4> Operations;<br>
> +  Operations.reserve(AllUpdates.size());<br>
> +<br>
> +  for (const auto &U : AllUpdates) {<br>
> +    NodePtr From = U.getFrom();<br>
> +    NodePtr To = U.getTo();<br>
> +    if (InverseGraph)<br>
> +      std::swap(From, To); // Reverse edge for postdominators.<br>
> +<br>
> +    Operations[{From, To}] += (U.getKind() == UpdateKind::Insert ? 1 : -1);<br>
> +  }<br>
> +<br>
> +  Result.clear();<br>
> +  Result.reserve(Operations.size());<br>
> +  for (auto &Op : Operations) {<br>
> +    const int NumInsertions = Op.second;<br>
> +    assert(std::abs(NumInsertions) <= 1 && "Unbalanced operations!");<br>
> +    if (NumInsertions == 0)<br>
> +      continue;<br>
> +    const UpdateKind UK =<br>
> +        NumInsertions > 0 ? UpdateKind::Insert : UpdateKind::Delete;<br>
> +    Result.push_back({UK, Op.first.first, Op.first.second});<br>
> +  }<br>
> +<br>
> +  // Make the order consistent by not relying on pointer values within the<br>
> +  // set. Reuse the old Operations map.<br>
> +  // In the future, we should sort by something else to minimize the amount<br>
> +  // of work needed to perform the series of updates.<br>
> +  for (size_t i = 0, e = AllUpdates.size(); i != e; ++i) {<br>
> +    const auto &U = AllUpdates[i];<br>
> +    if (!InverseGraph)<br>
> +      Operations[{U.getFrom(), U.getTo()}] = int(i);<br>
> +    else<br>
> +      Operations[{U.getTo(), U.getFrom()}] = int(i);<br>
> +  }<br>
> +<br>
> +  llvm::sort(Result.begin(), Result.end(),<br>
> +             [&Operations](const Update<NodePtr> &A, const Update<NodePtr> &B) {<br>
> +               return Operations[{A.getFrom(), A.getTo()}] ><br>
> +                      Operations[{B.getFrom(), B.getTo()}];<br>
> +             });<br>
> +}<br>
> +<br>
> +} // end namespace cfg<br>
> +} // end namespace llvm<br>
> +<br>
> +#endif // LLVM_SUPPORT_CFGUPDATE_H<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>