llvm.org GIT mirror llvm / f921d44
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339689 91177308-0d34-0410-b5e6-96231b3b80d8 Alina Sbirlea 2 years ago
3 changed file(s) with 427 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
333333 PointerIteratorT(std::end(std::forward(Range))));
334334 }
335335
336 // Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,
337 // to create NodeRef = std::pair.
338 template
339 class WrappedPairNodeDataIterator
340 : public iterator_adaptor_base<
341 WrappedPairNodeDataIterator, ItType,
342 typename std::iterator_traits::iterator_category, NodeRef,
343 std::ptrdiff_t, NodeRef *, NodeRef &> {
344 using BaseT = iterator_adaptor_base<
345 WrappedPairNodeDataIterator, ItType,
346 typename std::iterator_traits::iterator_category, NodeRef,
347 std::ptrdiff_t, NodeRef *, NodeRef &>;
348
349 const DataRef DR;
350 mutable NodeRef NR;
351
352 public:
353 WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)
354 : BaseT(Begin), DR(DR) {
355 NR.first = DR;
356 }
357
358 NodeRef &operator*() const {
359 NR.second = *this->I;
360 return NR;
361 }
362 };
363
336364 } // end namespace llvm
337365
338366 #endif // LLVM_ADT_ITERATOR_H
0 //===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines specializations of GraphTraits that allows generic
10 // algorithms to see a different snapshot of a CFG.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_IR_CFGDIFF_H
15 #define LLVM_IR_CFGDIFF_H
16
17 #include "llvm/ADT/GraphTraits.h"
18 #include "llvm/ADT/iterator.h"
19 #include "llvm/ADT/iterator_range.h"
20 #include "llvm/IR/BasicBlock.h"
21 #include "llvm/IR/CFG.h"
22 #include "llvm/Support/CFGUpdate.h"
23 #include "llvm/Support/type_traits.h"
24 #include
25 #include
26 #include
27
28 // Two booleans are used to define orders in graphs:
29 // InverseGraph defines when we need to reverse the whole graph and is as such
30 // also equivalent to applying updates in reverse.
31 // InverseEdge defines whether we want to change the edges direction. E.g., for
32 // a non-inversed graph, the children are naturally the successors when
33 // InverseEdge is false and the predecessors when InverseEdge is true.
34
35 // We define two base clases that call into GraphDiff, one for successors
36 // (CFGSuccessors), where InverseEdge is false, and one for predecessors
37 // (CFGPredecessors), where InverseEdge is true.
38 // FIXME: Further refactoring may merge the two base classes into a single one
39 // templated / parametrized on using succ_iterator/pred_iterator and false/true
40 // for the InverseEdge.
41
42 // CFGViewSuccessors and CFGViewPredecessors, both can be parametrized to
43 // consider the graph inverted or not (i.e. InverseGraph). Successors
44 // implicitly has InverseEdge = false and Predecessors implicitly has
45 // InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits
46 // instantiations that follow define the value of InverseGraph.
47
48 // GraphTraits instantiations:
49 // - GraphDiff is equivalent to InverseGraph = false
50 // - GraphDiff> is equivalent to InverseGraph = true
51 // - second pair item is BasicBlock *, then InverseEdge = false (so it inherits
52 // from CFGViewSuccessors).
53 // - second pair item is Inverse, then InverseEdge = true (so it
54 // inherits from CFGViewPredecessors).
55
56 // The 4 GraphTraits are as follows:
57 // 1. std::pair *, BasicBlock *>> :
58 // CFGViewSuccessors
59 // Regular CFG, children means successors, InverseGraph = false,
60 // InverseEdge = false.
61 // 2. std::pair> *, BasicBlock *>> :
62 // CFGViewSuccessors
63 // Reverse the graph, get successors but reverse-apply updates,
64 // InverseGraph = true, InverseEdge = false.
65 // 3. std::pair *, Inverse>> :
66 // CFGViewPredecessors
67 // Regular CFG, reverse edges, so children mean predecessors,
68 // InverseGraph = false, InverseEdge = true.
69 // 4. std::pair> *, Inverse>
70 // : CFGViewPredecessors
71 // Reverse the graph and the edges, InverseGraph = true, InverseEdge = true.
72
73 namespace llvm {
74
75 // GraphDiff defines a CFG snapshot: given a set of Update, provide
76 // utilities to skip edges marked as deleted and return a set of edges marked as
77 // newly inserted. The current diff treats the CFG as a graph rather than a
78 // multigraph. Added edges are pruned to be unique, and deleted edges will
79 // remove all existing edges between two blocks.
80 template class GraphDiff {
81 using UpdateMapType = SmallDenseMap>;
82 UpdateMapType SuccInsert;
83 UpdateMapType SuccDelete;
84 UpdateMapType PredInsert;
85 UpdateMapType PredDelete;
86 // Using a singleton empty vector for all BasicBlock requests with no
87 // children.
88 SmallVector Empty;
89
90 void printMap(raw_ostream &OS, const UpdateMapType &M) const {
91 for (auto Pair : M)
92 for (auto Child : Pair.second) {
93 OS << "(";
94 Pair.first->printAsOperand(OS, false);
95 OS << ", ";
96 Child->printAsOperand(OS, false);
97 OS << ") ";
98 }
99 OS << "\n";
100 }
101
102 public:
103 GraphDiff() {}
104 GraphDiff(ArrayRef> Updates, bool InverseGraph = false) {
105 SmallVector, 4> LegalizedUpdates;
106 cfg::LegalizeUpdates(Updates, LegalizedUpdates, InverseGraph);
107 for (auto U : LegalizedUpdates) {
108 if (U.getKind() == cfg::UpdateKind::Insert) {
109 SuccInsert[U.getFrom()].push_back(U.getTo());
110 PredInsert[U.getTo()].push_back(U.getFrom());
111 } else {
112 SuccDelete[U.getFrom()].push_back(U.getTo());
113 PredDelete[U.getTo()].push_back(U.getFrom());
114 }
115 }
116 }
117
118 bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge,
119 bool InverseGraph) 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
129 iterator_range::const_iterator>
130 getAddedChildren(const NodePtr BB, bool InverseEdge,
131 bool InverseGraph) const {
132 auto &InsertChildren =
133 (InverseEdge != InverseGraph) ? PredInsert : SuccInsert;
134 auto It = InsertChildren.find(BB);
135 if (It == InsertChildren.end())
136 return make_range(Empty.begin(), Empty.end());
137 return make_range(It->second.begin(), It->second.end());
138 }
139
140 void print(raw_ostream &OS) const {
141 OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
142 "===== (Note: notion of children/inverse_children depends on "
143 "the direction of edges and the graph.)\n";
144 OS << "Children to insert:\n\t";
145 printMap(OS, SuccInsert);
146 OS << "Children to delete:\n\t";
147 printMap(OS, SuccDelete);
148 OS << "Inverse_children to insert:\n\t";
149 printMap(OS, PredInsert);
150 OS << "Inverse_children to delete:\n\t";
151 printMap(OS, PredDelete);
152 OS << "\n";
153 }
154
155 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
156 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
157 #endif
158 };
159
160 template struct CFGViewSuccessors {
161 using DataRef = const GraphDiff *;
162 using NodeRef = std::pair;
163
164 using ExistingChildIterator =
165 WrappedPairNodeDataIterator;
166 struct DeletedEdgesFilter {
167 BasicBlock *BB;
168 DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};
169 bool operator()(NodeRef N) const {
170 return !N.first->ignoreChild(BB, N.second, false, InverseGraph);
171 }
172 };
173 using FilterExistingChildrenIterator =
174 filter_iterator;
175
176 using vec_iterator = SmallVectorImpl::const_iterator;
177 using AddNewChildrenIterator =
178 WrappedPairNodeDataIterator;
179 using ChildIteratorType =
180 concat_iterator
181 AddNewChildrenIterator>;
182
183 static ChildIteratorType child_begin(NodeRef N) {
184 auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);
185 // filter iterator init:
186 auto firstit = make_filter_range(
187 make_range({succ_begin(N.second), N.first},
188 {succ_end(N.second), N.first}),
189 DeletedEdgesFilter(N.second));
190 // new inserts iterator init:
191 auto secondit = make_range(
192 {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
193
194 return concat_iterator
195 AddNewChildrenIterator>(firstit, secondit);
196 }
197
198 static ChildIteratorType child_end(NodeRef N) {
199 auto InsertVec = N.first->getAddedChildren(N.second, false, InverseGraph);
200 // filter iterator init:
201 auto firstit = make_filter_range(
202 make_range({succ_end(N.second), N.first},
203 {succ_end(N.second), N.first}),
204 DeletedEdgesFilter(N.second));
205 // new inserts iterator init:
206 auto secondit = make_range(
207 {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
208
209 return concat_iterator
210 AddNewChildrenIterator>(firstit, secondit);
211 }
212 };
213
214 template struct CFGViewPredecessors {
215 using DataRef = const GraphDiff *;
216 using NodeRef = std::pair;
217
218 using ExistingChildIterator =
219 WrappedPairNodeDataIterator;
220 struct DeletedEdgesFilter {
221 BasicBlock *BB;
222 DeletedEdgesFilter(BasicBlock *BB) : BB(BB){};
223 bool operator()(NodeRef N) const {
224 return !N.first->ignoreChild(BB, N.second, true, InverseGraph);
225 }
226 };
227 using FilterExistingChildrenIterator =
228 filter_iterator;
229
230 using vec_iterator = SmallVectorImpl::const_iterator;
231 using AddNewChildrenIterator =
232 WrappedPairNodeDataIterator;
233 using ChildIteratorType =
234 concat_iterator
235 AddNewChildrenIterator>;
236
237 static ChildIteratorType child_begin(NodeRef N) {
238 auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);
239 // filter iterator init:
240 auto firstit = make_filter_range(
241 make_range({pred_begin(N.second), N.first},
242 {pred_end(N.second), N.first}),
243 DeletedEdgesFilter(N.second));
244 // new inserts iterator init:
245 auto secondit = make_range(
246 {InsertVec.begin(), N.first}, {InsertVec.end(), N.first});
247
248 return concat_iterator
249 AddNewChildrenIterator>(firstit, secondit);
250 }
251
252 static ChildIteratorType child_end(NodeRef N) {
253 auto InsertVec = N.first->getAddedChildren(N.second, true, InverseGraph);
254 // filter iterator init:
255 auto firstit = make_filter_range(
256 make_range({pred_end(N.second), N.first},
257 {pred_end(N.second), N.first}),
258 DeletedEdgesFilter(N.second));
259 // new inserts iterator init:
260 auto secondit = make_range(
261 {InsertVec.end(), N.first}, {InsertVec.end(), N.first});
262
263 return concat_iterator
264 AddNewChildrenIterator>(firstit, secondit);
265 }
266 };
267
268 template <>
269 struct GraphTraits *, BasicBlock *>>
270 : CFGViewSuccessors {};
271 template <>
272 struct GraphTraits<
273 std::pair> *, BasicBlock *>>
274 : CFGViewSuccessors {};
275 template <>
276 struct GraphTraits<
277 std::pair *, Inverse>>
278 : CFGViewPredecessors {};
279 template <>
280 struct GraphTraits<
281 std::pair> *, Inverse>>
282 : CFGViewPredecessors {};
283 } // end namespace llvm
284
285 #endif // LLVM_IR_CFGDIFF_H
0 //===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a CFG Edge Update: Insert or Delete, and two Nodes as the
10 // Edge ends.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_SUPPORT_CFGUPDATE_H
15 #define LLVM_SUPPORT_CFGUPDATE_H
16
17 #include "llvm/Support/Debug.h"
18
19 namespace llvm {
20 namespace cfg {
21 enum class UpdateKind : unsigned char { Insert, Delete };
22
23 template class Update {
24 using NodeKindPair = PointerIntPair;
25 NodePtr From;
26 NodeKindPair ToAndKind;
27
28 public:
29 Update(UpdateKind Kind, NodePtr From, NodePtr To)
30 : From(From), ToAndKind(To, Kind) {}
31
32 UpdateKind getKind() const { return ToAndKind.getInt(); }
33 NodePtr getFrom() const { return From; }
34 NodePtr getTo() const { return ToAndKind.getPointer(); }
35 bool operator==(const Update &RHS) const {
36 return From == RHS.From && ToAndKind == RHS.ToAndKind;
37 }
38
39 void print(raw_ostream &OS) const {
40 OS << (getKind() == UpdateKind::Insert ? "Insert " : "Delete ");
41 getFrom()->printAsOperand(OS, false);
42 OS << " -> ";
43 getTo()->printAsOperand(OS, false);
44 }
45
46 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
47 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
48 #endif
49 };
50
51 // LegalizeUpdates function simplifies updates assuming a graph structure.
52 // This function serves double purpose:
53 // a) It removes redundant updates, which makes it easier to reverse-apply
54 // them when traversing CFG.
55 // b) It optimizes away updates that cancel each other out, as the end result
56 // is the same.
57 template
58 void LegalizeUpdates(ArrayRef> AllUpdates,
59 SmallVectorImpl> &Result,
60 bool InverseGraph) {
61 // Count the total number of inserions of each edge.
62 // Each insertion adds 1 and deletion subtracts 1. The end number should be
63 // one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
64 // of updates contains multiple updates of the same kind and we assert for
65 // that case.
66 SmallDenseMap, int, 4> Operations;
67 Operations.reserve(AllUpdates.size());
68
69 for (const auto &U : AllUpdates) {
70 NodePtr From = U.getFrom();
71 NodePtr To = U.getTo();
72 if (InverseGraph)
73 std::swap(From, To); // Reverse edge for postdominators.
74
75 Operations[{From, To}] += (U.getKind() == UpdateKind::Insert ? 1 : -1);
76 }
77
78 Result.clear();
79 Result.reserve(Operations.size());
80 for (auto &Op : Operations) {
81 const int NumInsertions = Op.second;
82 assert(std::abs(NumInsertions) <= 1 && "Unbalanced operations!");
83 if (NumInsertions == 0)
84 continue;
85 const UpdateKind UK =
86 NumInsertions > 0 ? UpdateKind::Insert : UpdateKind::Delete;
87 Result.push_back({UK, Op.first.first, Op.first.second});
88 }
89
90 // Make the order consistent by not relying on pointer values within the
91 // set. Reuse the old Operations map.
92 // In the future, we should sort by something else to minimize the amount
93 // of work needed to perform the series of updates.
94 for (size_t i = 0, e = AllUpdates.size(); i != e; ++i) {
95 const auto &U = AllUpdates[i];
96 if (!InverseGraph)
97 Operations[{U.getFrom(), U.getTo()}] = int(i);
98 else
99 Operations[{U.getTo(), U.getFrom()}] = int(i);
100 }
101
102 llvm::sort(Result.begin(), Result.end(),
103 [&Operations](const Update &A, const Update &B) {
104 return Operations[{A.getFrom(), A.getTo()}] >
105 Operations[{B.getFrom(), B.getTo()}];
106 });
107 }
108
109 } // end namespace cfg
110 } // end namespace llvm
111
112 #endif // LLVM_SUPPORT_CFGUPDATE_H