LLVM  8.0.1
CFGDiff.h
Go to the documentation of this file.
1 //===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines specializations of GraphTraits that allows generic
11 // algorithms to see a different snapshot of a CFG.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_IR_CFGDIFF_H
16 #define LLVM_IR_CFGDIFF_H
17 
18 #include "llvm/ADT/GraphTraits.h"
19 #include "llvm/ADT/iterator.h"
21 #include "llvm/IR/BasicBlock.h"
22 #include "llvm/IR/CFG.h"
23 #include "llvm/Support/CFGUpdate.h"
25 #include <cassert>
26 #include <cstddef>
27 #include <iterator>
28 
29 // Two booleans are used to define orders in graphs:
30 // InverseGraph defines when we need to reverse the whole graph and is as such
31 // also equivalent to applying updates in reverse.
32 // InverseEdge defines whether we want to change the edges direction. E.g., for
33 // a non-inversed graph, the children are naturally the successors when
34 // InverseEdge is false and the predecessors when InverseEdge is true.
35 
36 // We define two base clases that call into GraphDiff, one for successors
37 // (CFGSuccessors), where InverseEdge is false, and one for predecessors
38 // (CFGPredecessors), where InverseEdge is true.
39 // FIXME: Further refactoring may merge the two base classes into a single one
40 // templated / parametrized on using succ_iterator/pred_iterator and false/true
41 // for the InverseEdge.
42 
43 // CFGViewSuccessors and CFGViewPredecessors, both can be parametrized to
44 // consider the graph inverted or not (i.e. InverseGraph). Successors
45 // implicitly has InverseEdge = false and Predecessors implicitly has
46 // InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits
47 // instantiations that follow define the value of InverseGraph.
48 
49 // GraphTraits instantiations:
50 // - GraphDiff<BasicBlock *> is equivalent to InverseGraph = false
51 // - GraphDiff<Inverse<BasicBlock *>> is equivalent to InverseGraph = true
52 // - second pair item is BasicBlock *, then InverseEdge = false (so it inherits
53 // from CFGViewSuccessors).
54 // - second pair item is Inverse<BasicBlock *>, then InverseEdge = true (so it
55 // inherits from CFGViewPredecessors).
56 
57 // The 4 GraphTraits are as follows:
58 // 1. std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>> :
59 // CFGViewSuccessors<false>
60 // Regular CFG, children means successors, InverseGraph = false,
61 // InverseEdge = false.
62 // 2. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>> :
63 // CFGViewSuccessors<true>
64 // Reverse the graph, get successors but reverse-apply updates,
65 // InverseGraph = true, InverseEdge = false.
66 // 3. std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>> :
67 // CFGViewPredecessors<false>
68 // Regular CFG, reverse edges, so children mean predecessors,
69 // InverseGraph = false, InverseEdge = true.
70 // 4. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>>
71 // : CFGViewPredecessors<true>
72 // Reverse the graph and the edges, InverseGraph = true, InverseEdge = true.
73 
74 namespace llvm {
75 
76 // GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provide
77 // utilities to skip edges marked as deleted and return a set of edges marked as
78 // newly inserted. The current diff treats the CFG as a graph rather than a
79 // multigraph. Added edges are pruned to be unique, and deleted edges will
80 // remove all existing edges between two blocks.
81 template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
83  UpdateMapType SuccInsert;
84  UpdateMapType SuccDelete;
85  UpdateMapType PredInsert;
86  UpdateMapType PredDelete;
87  // Using a singleton empty vector for all BasicBlock requests with no
88  // children.
90 
91  void printMap(raw_ostream &OS, const UpdateMapType &M) const {
92  for (auto Pair : M)
93  for (auto Child : Pair.second) {
94  OS << "(";
95  Pair.first->printAsOperand(OS, false);
96  OS << ", ";
97  Child->printAsOperand(OS, false);
98  OS << ") ";
99  }
100  OS << "\n";
101  }
102 
103 public:
106  SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
107  cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
108  for (auto U : LegalizedUpdates) {
109  if (U.getKind() == cfg::UpdateKind::Insert) {
110  SuccInsert[U.getFrom()].push_back(U.getTo());
111  PredInsert[U.getTo()].push_back(U.getFrom());
112  } else {
113  SuccDelete[U.getFrom()].push_back(U.getTo());
114  PredDelete[U.getTo()].push_back(U.getFrom());
115  }
116  }
117  }
118 
119  bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge) const {
120  auto &DeleteChildren =
121  (InverseEdge != InverseGraph) ? PredDelete : SuccDelete;
122  auto It = DeleteChildren.find(BB);
123  if (It == DeleteChildren.end())
124  return false;
125  auto &EdgesForBB = It->second;
126  return llvm::find(EdgesForBB, EdgeEnd) != EdgesForBB.end();
127  }
128 
130  getAddedChildren(const NodePtr BB, bool InverseEdge) const {
131  auto &InsertChildren =
132  (InverseEdge != InverseGraph) ? PredInsert : SuccInsert;
133  auto It = InsertChildren.find(BB);
134  if (It == InsertChildren.end())
135  return make_range(Empty.begin(), Empty.end());
136  return make_range(It->second.begin(), It->second.end());
137  }
138 
139  void print(raw_ostream &OS) const {
140  OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
141  "===== (Note: notion of children/inverse_children depends on "
142  "the direction of edges and the graph.)\n";
143  OS << "Children to insert:\n\t";
144  printMap(OS, SuccInsert);
145  OS << "Children to delete:\n\t";
146  printMap(OS, SuccDelete);
147  OS << "Inverse_children to insert:\n\t";
148  printMap(OS, PredInsert);
149  OS << "Inverse_children to delete:\n\t";
150  printMap(OS, PredDelete);
151  OS << "\n";
152  }
153 
154 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
155  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
156 #endif
157 };
158 
159 template <bool InverseGraph = false> struct CFGViewSuccessors {
161  using NodeRef = std::pair<DataRef, BasicBlock *>;
162 
163  using ExistingChildIterator =
168  bool operator()(NodeRef N) const {
169  return !N.first->ignoreChild(BB, N.second, false);
170  }
171  };
174 
176  using AddNewChildrenIterator =
178  using ChildIteratorType =
181 
182  static ChildIteratorType child_begin(NodeRef N) {
183  auto InsertVec = N.first->getAddedChildren(N.second, false);
184  // filter iterator init:
185  auto firstit = make_filter_range(
186  make_range<ExistingChildIterator>({succ_begin(N.second), N.first},
187  {succ_end(N.second), N.first}),
188  DeletedEdgesFilter(N.second));
189  // new inserts iterator init:
190  auto secondit = make_range<AddNewChildrenIterator>(
191  {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
192 
193  return concat_iterator<NodeRef, FilterExistingChildrenIterator,
194  AddNewChildrenIterator>(firstit, secondit);
195  }
196 
197  static ChildIteratorType child_end(NodeRef N) {
198  auto InsertVec = N.first->getAddedChildren(N.second, false);
199  // filter iterator init:
200  auto firstit = make_filter_range(
201  make_range<ExistingChildIterator>({succ_end(N.second), N.first},
202  {succ_end(N.second), N.first}),
203  DeletedEdgesFilter(N.second));
204  // new inserts iterator init:
205  auto secondit = make_range<AddNewChildrenIterator>(
206  {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
207 
208  return concat_iterator<NodeRef, FilterExistingChildrenIterator,
209  AddNewChildrenIterator>(firstit, secondit);
210  }
211 };
212 
213 template <bool InverseGraph = false> struct CFGViewPredecessors {
215  using NodeRef = std::pair<DataRef, BasicBlock *>;
216 
217  using ExistingChildIterator =
222  bool operator()(NodeRef N) const {
223  return !N.first->ignoreChild(BB, N.second, true);
224  }
225  };
228 
230  using AddNewChildrenIterator =
232  using ChildIteratorType =
234  AddNewChildrenIterator>;
235 
236  static ChildIteratorType child_begin(NodeRef N) {
237  auto InsertVec = N.first->getAddedChildren(N.second, true);
238  // filter iterator init:
239  auto firstit = make_filter_range(
240  make_range<ExistingChildIterator>({pred_begin(N.second), N.first},
241  {pred_end(N.second), N.first}),
242  DeletedEdgesFilter(N.second));
243  // new inserts iterator init:
244  auto secondit = make_range<AddNewChildrenIterator>(
245  {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
246 
247  return concat_iterator<NodeRef, FilterExistingChildrenIterator,
248  AddNewChildrenIterator>(firstit, secondit);
249  }
250 
251  static ChildIteratorType child_end(NodeRef N) {
252  auto InsertVec = N.first->getAddedChildren(N.second, true);
253  // filter iterator init:
254  auto firstit = make_filter_range(
255  make_range<ExistingChildIterator>({pred_end(N.second), N.first},
256  {pred_end(N.second), N.first}),
257  DeletedEdgesFilter(N.second));
258  // new inserts iterator init:
259  auto secondit = make_range<AddNewChildrenIterator>(
260  {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
261 
262  return concat_iterator<NodeRef, FilterExistingChildrenIterator,
263  AddNewChildrenIterator>(firstit, secondit);
264  }
265 };
266 
267 template <>
268 struct GraphTraits<
269  std::pair<const GraphDiff<BasicBlock *, false> *, BasicBlock *>>
270  : CFGViewSuccessors<false> {};
271 template <>
272 struct GraphTraits<
273  std::pair<const GraphDiff<BasicBlock *, true> *, BasicBlock *>>
274  : CFGViewSuccessors<true> {};
275 template <>
276 struct GraphTraits<
277  std::pair<const GraphDiff<BasicBlock *, false> *, Inverse<BasicBlock *>>>
278  : CFGViewPredecessors<false> {};
279 template <>
280 struct GraphTraits<
281  std::pair<const GraphDiff<BasicBlock *, true> *, Inverse<BasicBlock *>>>
282  : CFGViewPredecessors<true> {};
283 } // end namespace llvm
284 
285 #endif // LLVM_IR_CFGDIFF_H
This class represents lattice values for constants.
Definition: AllocatorList.h:24
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
static ChildIteratorType child_begin(NodeRef N)
Definition: CFGDiff.h:236
std::pair< DataRef, BasicBlock *> NodeRef
Definition: CFGDiff.h:215
static ChildIteratorType child_begin(NodeRef N)
Definition: CFGDiff.h:182
Definition: BitVector.h:938
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
LLVM_DUMP_METHOD void dump() const
Definition: CFGDiff.h:155
#define LLVM_DUMP_METHOD
Definition: Compiler.h:74
bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge) const
Definition: CFGDiff.h:119
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Definition: Interval.h:103
std::pair< DataRef, BasicBlock *> NodeRef
Definition: CFGDiff.h:161
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
Interval::succ_iterator succ_end(Interval *I)
Definition: Interval.h:106
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:176
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
std::shared_ptr< Node > NodePtr
Short-hand for a Node pointer.
Definition: MsgPackTypes.h:33
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Definition: Interval.h:113
Interval::pred_iterator pred_end(Interval *I)
Definition: Interval.h:116
void print(raw_ostream &OS) const
Definition: CFGDiff.h:139
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1207
static ChildIteratorType child_end(NodeRef N)
Definition: CFGDiff.h:197
static ChildIteratorType child_end(NodeRef N)
Definition: CFGDiff.h:251
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
GraphDiff(ArrayRef< cfg::Update< NodePtr >> Updates)
Definition: CFGDiff.h:105
SmallVectorImpl< BasicBlock *>::const_iterator vec_iterator
Definition: CFGDiff.h:175
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
A range adaptor for a pair of iterators.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
#define N
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition: STLExtras.h:428
iterator_range< typename SmallVectorImpl< NodePtr >::const_iterator > getAddedChildren(const NodePtr BB, bool InverseEdge) const
Definition: CFGDiff.h:130
SmallVectorImpl< BasicBlock *>::const_iterator vec_iterator
Definition: CFGDiff.h:229
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
Specialization of filter_iterator_base for forward iteration only.
Definition: STLExtras.h:354
Iterator wrapper that concatenates sequences together.
Definition: STLExtras.h:813