Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlanCFG.h
35269 views
1
//===- VPlanCFG.h - GraphTraits for VP blocks -------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// Specializations of GraphTraits that allow VPBlockBase graphs to be
9
/// treated as proper graphs for generic algorithms;
10
//===----------------------------------------------------------------------===//
11
12
#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
13
#define LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
14
15
#include "VPlan.h"
16
#include "llvm/ADT/DepthFirstIterator.h"
17
#include "llvm/ADT/GraphTraits.h"
18
#include "llvm/ADT/SmallVector.h"
19
20
namespace llvm {
21
22
//===----------------------------------------------------------------------===//
23
// GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs //
24
//===----------------------------------------------------------------------===//
25
26
/// Iterator to traverse all successors of a VPBlockBase node. This includes the
27
/// entry node of VPRegionBlocks. Exit blocks of a region implicitly have their
28
/// parent region's successors. This ensures all blocks in a region are visited
29
/// before any blocks in a successor region when doing a reverse post-order
30
// traversal of the graph. Region blocks themselves traverse only their entries
31
// directly and not their successors. Those will be traversed when a region's
32
// exiting block is traversed
33
template <typename BlockPtrTy>
34
class VPAllSuccessorsIterator
35
: public iterator_facade_base<VPAllSuccessorsIterator<BlockPtrTy>,
36
std::bidirectional_iterator_tag,
37
VPBlockBase> {
38
BlockPtrTy Block;
39
/// Index of the current successor. For VPBasicBlock nodes, this simply is the
40
/// index for the successor array. For VPRegionBlock, SuccessorIdx == 0 is
41
/// used for the region's entry block, and SuccessorIdx - 1 are the indices
42
/// for the successor array.
43
size_t SuccessorIdx;
44
45
static BlockPtrTy getBlockWithSuccs(BlockPtrTy Current) {
46
while (Current && Current->getNumSuccessors() == 0)
47
Current = Current->getParent();
48
return Current;
49
}
50
51
/// Templated helper to dereference successor \p SuccIdx of \p Block. Used by
52
/// both the const and non-const operator* implementations.
53
template <typename T1> static T1 deref(T1 Block, unsigned SuccIdx) {
54
if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
55
assert(SuccIdx == 0);
56
return R->getEntry();
57
}
58
59
// For exit blocks, use the next parent region with successors.
60
return getBlockWithSuccs(Block)->getSuccessors()[SuccIdx];
61
}
62
63
public:
64
/// Used by iterator_facade_base with bidirectional_iterator_tag.
65
using reference = BlockPtrTy;
66
67
VPAllSuccessorsIterator(BlockPtrTy Block, size_t Idx = 0)
68
: Block(Block), SuccessorIdx(Idx) {}
69
VPAllSuccessorsIterator(const VPAllSuccessorsIterator &Other)
70
: Block(Other.Block), SuccessorIdx(Other.SuccessorIdx) {}
71
72
VPAllSuccessorsIterator &operator=(const VPAllSuccessorsIterator &R) {
73
Block = R.Block;
74
SuccessorIdx = R.SuccessorIdx;
75
return *this;
76
}
77
78
static VPAllSuccessorsIterator end(BlockPtrTy Block) {
79
if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
80
// Traverse through the region's entry node.
81
return {R, 1};
82
}
83
BlockPtrTy ParentWithSuccs = getBlockWithSuccs(Block);
84
unsigned NumSuccessors =
85
ParentWithSuccs ? ParentWithSuccs->getNumSuccessors() : 0;
86
return {Block, NumSuccessors};
87
}
88
89
bool operator==(const VPAllSuccessorsIterator &R) const {
90
return Block == R.Block && SuccessorIdx == R.SuccessorIdx;
91
}
92
93
const VPBlockBase *operator*() const { return deref(Block, SuccessorIdx); }
94
95
BlockPtrTy operator*() { return deref(Block, SuccessorIdx); }
96
97
VPAllSuccessorsIterator &operator++() {
98
SuccessorIdx++;
99
return *this;
100
}
101
102
VPAllSuccessorsIterator &operator--() {
103
SuccessorIdx--;
104
return *this;
105
}
106
107
VPAllSuccessorsIterator operator++(int X) {
108
VPAllSuccessorsIterator Orig = *this;
109
SuccessorIdx++;
110
return Orig;
111
}
112
};
113
114
/// Helper for GraphTraits specialization that traverses through VPRegionBlocks.
115
template <typename BlockTy> class VPBlockDeepTraversalWrapper {
116
BlockTy Entry;
117
118
public:
119
VPBlockDeepTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
120
BlockTy getEntry() { return Entry; }
121
};
122
123
/// GraphTraits specialization to recursively traverse VPBlockBase nodes,
124
/// including traversing through VPRegionBlocks. Exit blocks of a region
125
/// implicitly have their parent region's successors. This ensures all blocks in
126
/// a region are visited before any blocks in a successor region when doing a
127
/// reverse post-order traversal of the graph.
128
template <> struct GraphTraits<VPBlockDeepTraversalWrapper<VPBlockBase *>> {
129
using NodeRef = VPBlockBase *;
130
using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
131
132
static NodeRef getEntryNode(VPBlockDeepTraversalWrapper<VPBlockBase *> N) {
133
return N.getEntry();
134
}
135
136
static inline ChildIteratorType child_begin(NodeRef N) {
137
return ChildIteratorType(N);
138
}
139
140
static inline ChildIteratorType child_end(NodeRef N) {
141
return ChildIteratorType::end(N);
142
}
143
};
144
145
template <>
146
struct GraphTraits<VPBlockDeepTraversalWrapper<const VPBlockBase *>> {
147
using NodeRef = const VPBlockBase *;
148
using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
149
150
static NodeRef
151
getEntryNode(VPBlockDeepTraversalWrapper<const VPBlockBase *> N) {
152
return N.getEntry();
153
}
154
155
static inline ChildIteratorType child_begin(NodeRef N) {
156
return ChildIteratorType(N);
157
}
158
159
static inline ChildIteratorType child_end(NodeRef N) {
160
return ChildIteratorType::end(N);
161
}
162
};
163
164
/// Helper for GraphTraits specialization that does not traverses through
165
/// VPRegionBlocks.
166
template <typename BlockTy> class VPBlockShallowTraversalWrapper {
167
BlockTy Entry;
168
169
public:
170
VPBlockShallowTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
171
BlockTy getEntry() { return Entry; }
172
};
173
174
template <> struct GraphTraits<VPBlockShallowTraversalWrapper<VPBlockBase *>> {
175
using NodeRef = VPBlockBase *;
176
using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
177
178
static NodeRef getEntryNode(VPBlockShallowTraversalWrapper<VPBlockBase *> N) {
179
return N.getEntry();
180
}
181
182
static inline ChildIteratorType child_begin(NodeRef N) {
183
return N->getSuccessors().begin();
184
}
185
186
static inline ChildIteratorType child_end(NodeRef N) {
187
return N->getSuccessors().end();
188
}
189
};
190
191
template <>
192
struct GraphTraits<VPBlockShallowTraversalWrapper<const VPBlockBase *>> {
193
using NodeRef = const VPBlockBase *;
194
using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::const_iterator;
195
196
static NodeRef
197
getEntryNode(VPBlockShallowTraversalWrapper<const VPBlockBase *> N) {
198
return N.getEntry();
199
}
200
201
static inline ChildIteratorType child_begin(NodeRef N) {
202
return N->getSuccessors().begin();
203
}
204
205
static inline ChildIteratorType child_end(NodeRef N) {
206
return N->getSuccessors().end();
207
}
208
};
209
210
/// Returns an iterator range to traverse the graph starting at \p G in
211
/// depth-first order. The iterator won't traverse through region blocks.
212
inline iterator_range<
213
df_iterator<VPBlockShallowTraversalWrapper<VPBlockBase *>>>
214
vp_depth_first_shallow(VPBlockBase *G) {
215
return depth_first(VPBlockShallowTraversalWrapper<VPBlockBase *>(G));
216
}
217
inline iterator_range<
218
df_iterator<VPBlockShallowTraversalWrapper<const VPBlockBase *>>>
219
vp_depth_first_shallow(const VPBlockBase *G) {
220
return depth_first(VPBlockShallowTraversalWrapper<const VPBlockBase *>(G));
221
}
222
223
/// Returns an iterator range to traverse the graph starting at \p G in
224
/// depth-first order while traversing through region blocks.
225
inline iterator_range<df_iterator<VPBlockDeepTraversalWrapper<VPBlockBase *>>>
226
vp_depth_first_deep(VPBlockBase *G) {
227
return depth_first(VPBlockDeepTraversalWrapper<VPBlockBase *>(G));
228
}
229
inline iterator_range<
230
df_iterator<VPBlockDeepTraversalWrapper<const VPBlockBase *>>>
231
vp_depth_first_deep(const VPBlockBase *G) {
232
return depth_first(VPBlockDeepTraversalWrapper<const VPBlockBase *>(G));
233
}
234
235
// The following set of template specializations implement GraphTraits to treat
236
// any VPBlockBase as a node in a graph of VPBlockBases. It's important to note
237
// that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the
238
// VPBlockBase is a VPRegionBlock, this specialization provides access to its
239
// successors/predecessors but not to the blocks inside the region.
240
241
template <> struct GraphTraits<VPBlockBase *> {
242
using NodeRef = VPBlockBase *;
243
using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
244
245
static NodeRef getEntryNode(NodeRef N) { return N; }
246
247
static inline ChildIteratorType child_begin(NodeRef N) {
248
return ChildIteratorType(N);
249
}
250
251
static inline ChildIteratorType child_end(NodeRef N) {
252
return ChildIteratorType::end(N);
253
}
254
};
255
256
template <> struct GraphTraits<const VPBlockBase *> {
257
using NodeRef = const VPBlockBase *;
258
using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
259
260
static NodeRef getEntryNode(NodeRef N) { return N; }
261
262
static inline ChildIteratorType child_begin(NodeRef N) {
263
return ChildIteratorType(N);
264
}
265
266
static inline ChildIteratorType child_end(NodeRef N) {
267
return ChildIteratorType::end(N);
268
}
269
};
270
271
/// Inverse graph traits are not implemented yet.
272
/// TODO: Implement a version of VPBlockNonRecursiveTraversalWrapper to traverse
273
/// predecessors recursively through regions.
274
template <> struct GraphTraits<Inverse<VPBlockBase *>> {
275
using NodeRef = VPBlockBase *;
276
using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
277
278
static NodeRef getEntryNode(Inverse<NodeRef> B) {
279
llvm_unreachable("not implemented");
280
}
281
282
static inline ChildIteratorType child_begin(NodeRef N) {
283
llvm_unreachable("not implemented");
284
}
285
286
static inline ChildIteratorType child_end(NodeRef N) {
287
llvm_unreachable("not implemented");
288
}
289
};
290
291
template <> struct GraphTraits<VPlan *> {
292
using GraphRef = VPlan *;
293
using NodeRef = VPBlockBase *;
294
using nodes_iterator = df_iterator<NodeRef>;
295
296
static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }
297
298
static nodes_iterator nodes_begin(GraphRef N) {
299
return nodes_iterator::begin(N->getEntry());
300
}
301
302
static nodes_iterator nodes_end(GraphRef N) {
303
// df_iterator::end() returns an empty iterator so the node used doesn't
304
// matter.
305
return nodes_iterator::end(N->getEntry());
306
}
307
};
308
309
} // namespace llvm
310
311
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
312
313