xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanCFG.h (revision 05fbc3830d05878a0521a3e07aa1e469905ce732)
1cd16a3f0SFlorian Hahn //===- VPlanCFG.h - GraphTraits for VP blocks -------------------*- C++ -*-===//
2cd16a3f0SFlorian Hahn //
3cd16a3f0SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cd16a3f0SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information.
5cd16a3f0SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cd16a3f0SFlorian Hahn //
7cd16a3f0SFlorian Hahn //===----------------------------------------------------------------------===//
8cd16a3f0SFlorian Hahn /// Specializations of GraphTraits that allow VPBlockBase graphs to be
9cd16a3f0SFlorian Hahn /// treated as proper graphs for generic algorithms;
10cd16a3f0SFlorian Hahn //===----------------------------------------------------------------------===//
11cd16a3f0SFlorian Hahn 
12cd16a3f0SFlorian Hahn #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
13cd16a3f0SFlorian Hahn #define LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
14cd16a3f0SFlorian Hahn 
15cd16a3f0SFlorian Hahn #include "VPlan.h"
16*05fbc383SFlorian Hahn #include "VPlanUtils.h"
176f999769SFlorian Hahn #include "llvm/ADT/DepthFirstIterator.h"
18cd16a3f0SFlorian Hahn #include "llvm/ADT/GraphTraits.h"
19cd16a3f0SFlorian Hahn #include "llvm/ADT/SmallVector.h"
20cd16a3f0SFlorian Hahn 
21cd16a3f0SFlorian Hahn namespace llvm {
22cd16a3f0SFlorian Hahn 
23cd16a3f0SFlorian Hahn //===----------------------------------------------------------------------===//
24cd16a3f0SFlorian Hahn // GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs     //
25cd16a3f0SFlorian Hahn //===----------------------------------------------------------------------===//
26cd16a3f0SFlorian Hahn 
27cd16a3f0SFlorian Hahn /// Iterator to traverse all successors of a VPBlockBase node. This includes the
28cd16a3f0SFlorian Hahn /// entry node of VPRegionBlocks. Exit blocks of a region implicitly have their
29cd16a3f0SFlorian Hahn /// parent region's successors. This ensures all blocks in a region are visited
30cd16a3f0SFlorian Hahn /// before any blocks in a successor region when doing a reverse post-order
31feee22dbSFlorian Hahn // traversal of the graph. Region blocks themselves traverse only their entries
32feee22dbSFlorian Hahn // directly and not their successors. Those will be traversed when a region's
33feee22dbSFlorian Hahn // exiting block is traversed
34cd16a3f0SFlorian Hahn template <typename BlockPtrTy>
35cd16a3f0SFlorian Hahn class VPAllSuccessorsIterator
36cd16a3f0SFlorian Hahn     : public iterator_facade_base<VPAllSuccessorsIterator<BlockPtrTy>,
37bf9e0da1SFlorian Hahn                                   std::bidirectional_iterator_tag,
38bf9e0da1SFlorian Hahn                                   VPBlockBase> {
39cd16a3f0SFlorian Hahn   BlockPtrTy Block;
40cd16a3f0SFlorian Hahn   /// Index of the current successor. For VPBasicBlock nodes, this simply is the
41cd16a3f0SFlorian Hahn   /// index for the successor array. For VPRegionBlock, SuccessorIdx == 0 is
42cd16a3f0SFlorian Hahn   /// used for the region's entry block, and SuccessorIdx - 1 are the indices
43cd16a3f0SFlorian Hahn   /// for the successor array.
44cd16a3f0SFlorian Hahn   size_t SuccessorIdx;
45cd16a3f0SFlorian Hahn 
46cd16a3f0SFlorian Hahn   static BlockPtrTy getBlockWithSuccs(BlockPtrTy Current) {
47cd16a3f0SFlorian Hahn     while (Current && Current->getNumSuccessors() == 0)
48cd16a3f0SFlorian Hahn       Current = Current->getParent();
49cd16a3f0SFlorian Hahn     return Current;
50cd16a3f0SFlorian Hahn   }
51cd16a3f0SFlorian Hahn 
52cd16a3f0SFlorian Hahn   /// Templated helper to dereference successor \p SuccIdx of \p Block. Used by
53cd16a3f0SFlorian Hahn   /// both the const and non-const operator* implementations.
54cd16a3f0SFlorian Hahn   template <typename T1> static T1 deref(T1 Block, unsigned SuccIdx) {
55cd16a3f0SFlorian Hahn     if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
56feee22dbSFlorian Hahn       assert(SuccIdx == 0);
57cd16a3f0SFlorian Hahn       return R->getEntry();
58cd16a3f0SFlorian Hahn     }
59cd16a3f0SFlorian Hahn 
60cd16a3f0SFlorian Hahn     // For exit blocks, use the next parent region with successors.
61cd16a3f0SFlorian Hahn     return getBlockWithSuccs(Block)->getSuccessors()[SuccIdx];
62cd16a3f0SFlorian Hahn   }
63cd16a3f0SFlorian Hahn 
64cd16a3f0SFlorian Hahn public:
65bf9e0da1SFlorian Hahn   /// Used by iterator_facade_base with bidirectional_iterator_tag.
66bf9e0da1SFlorian Hahn   using reference = BlockPtrTy;
67bf9e0da1SFlorian Hahn 
68cd16a3f0SFlorian Hahn   VPAllSuccessorsIterator(BlockPtrTy Block, size_t Idx = 0)
69cd16a3f0SFlorian Hahn       : Block(Block), SuccessorIdx(Idx) {}
70cd16a3f0SFlorian Hahn   VPAllSuccessorsIterator(const VPAllSuccessorsIterator &Other)
71cd16a3f0SFlorian Hahn       : Block(Other.Block), SuccessorIdx(Other.SuccessorIdx) {}
72cd16a3f0SFlorian Hahn 
73cd16a3f0SFlorian Hahn   VPAllSuccessorsIterator &operator=(const VPAllSuccessorsIterator &R) {
74cd16a3f0SFlorian Hahn     Block = R.Block;
75cd16a3f0SFlorian Hahn     SuccessorIdx = R.SuccessorIdx;
76cd16a3f0SFlorian Hahn     return *this;
77cd16a3f0SFlorian Hahn   }
78cd16a3f0SFlorian Hahn 
79cd16a3f0SFlorian Hahn   static VPAllSuccessorsIterator end(BlockPtrTy Block) {
80feee22dbSFlorian Hahn     if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
81feee22dbSFlorian Hahn       // Traverse through the region's entry node.
82feee22dbSFlorian Hahn       return {R, 1};
83feee22dbSFlorian Hahn     }
84cd16a3f0SFlorian Hahn     BlockPtrTy ParentWithSuccs = getBlockWithSuccs(Block);
85c9513839SFlorian Hahn     unsigned NumSuccessors =
86c9513839SFlorian Hahn         ParentWithSuccs ? ParentWithSuccs->getNumSuccessors() : 0;
87cd16a3f0SFlorian Hahn     return {Block, NumSuccessors};
88cd16a3f0SFlorian Hahn   }
89cd16a3f0SFlorian Hahn 
90cd16a3f0SFlorian Hahn   bool operator==(const VPAllSuccessorsIterator &R) const {
91cd16a3f0SFlorian Hahn     return Block == R.Block && SuccessorIdx == R.SuccessorIdx;
92cd16a3f0SFlorian Hahn   }
93cd16a3f0SFlorian Hahn 
94cd16a3f0SFlorian Hahn   const VPBlockBase *operator*() const { return deref(Block, SuccessorIdx); }
95cd16a3f0SFlorian Hahn 
96cd16a3f0SFlorian Hahn   BlockPtrTy operator*() { return deref(Block, SuccessorIdx); }
97cd16a3f0SFlorian Hahn 
98cd16a3f0SFlorian Hahn   VPAllSuccessorsIterator &operator++() {
99cd16a3f0SFlorian Hahn     SuccessorIdx++;
100cd16a3f0SFlorian Hahn     return *this;
101cd16a3f0SFlorian Hahn   }
102cd16a3f0SFlorian Hahn 
103bf9e0da1SFlorian Hahn   VPAllSuccessorsIterator &operator--() {
104bf9e0da1SFlorian Hahn     SuccessorIdx--;
105bf9e0da1SFlorian Hahn     return *this;
106bf9e0da1SFlorian Hahn   }
107bf9e0da1SFlorian Hahn 
108cd16a3f0SFlorian Hahn   VPAllSuccessorsIterator operator++(int X) {
109cd16a3f0SFlorian Hahn     VPAllSuccessorsIterator Orig = *this;
110cd16a3f0SFlorian Hahn     SuccessorIdx++;
111cd16a3f0SFlorian Hahn     return Orig;
112cd16a3f0SFlorian Hahn   }
113cd16a3f0SFlorian Hahn };
114cd16a3f0SFlorian Hahn 
115cd16a3f0SFlorian Hahn /// Helper for GraphTraits specialization that traverses through VPRegionBlocks.
116e2c43a54SFlorian Hahn template <typename BlockTy> class VPBlockDeepTraversalWrapper {
117cd16a3f0SFlorian Hahn   BlockTy Entry;
118cd16a3f0SFlorian Hahn 
119cd16a3f0SFlorian Hahn public:
120e2c43a54SFlorian Hahn   VPBlockDeepTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
121cd16a3f0SFlorian Hahn   BlockTy getEntry() { return Entry; }
122cd16a3f0SFlorian Hahn };
123cd16a3f0SFlorian Hahn 
124cd16a3f0SFlorian Hahn /// GraphTraits specialization to recursively traverse VPBlockBase nodes,
125cd16a3f0SFlorian Hahn /// including traversing through VPRegionBlocks.  Exit blocks of a region
126cd16a3f0SFlorian Hahn /// implicitly have their parent region's successors. This ensures all blocks in
127cd16a3f0SFlorian Hahn /// a region are visited before any blocks in a successor region when doing a
128cd16a3f0SFlorian Hahn /// reverse post-order traversal of the graph.
129e2c43a54SFlorian Hahn template <> struct GraphTraits<VPBlockDeepTraversalWrapper<VPBlockBase *>> {
130cd16a3f0SFlorian Hahn   using NodeRef = VPBlockBase *;
131cd16a3f0SFlorian Hahn   using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
132cd16a3f0SFlorian Hahn 
133e2c43a54SFlorian Hahn   static NodeRef getEntryNode(VPBlockDeepTraversalWrapper<VPBlockBase *> N) {
134cd16a3f0SFlorian Hahn     return N.getEntry();
135cd16a3f0SFlorian Hahn   }
136cd16a3f0SFlorian Hahn 
137cd16a3f0SFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
138cd16a3f0SFlorian Hahn     return ChildIteratorType(N);
139cd16a3f0SFlorian Hahn   }
140cd16a3f0SFlorian Hahn 
141cd16a3f0SFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
142cd16a3f0SFlorian Hahn     return ChildIteratorType::end(N);
143cd16a3f0SFlorian Hahn   }
144cd16a3f0SFlorian Hahn };
145cd16a3f0SFlorian Hahn 
146cd16a3f0SFlorian Hahn template <>
147e2c43a54SFlorian Hahn struct GraphTraits<VPBlockDeepTraversalWrapper<const VPBlockBase *>> {
148cd16a3f0SFlorian Hahn   using NodeRef = const VPBlockBase *;
149cd16a3f0SFlorian Hahn   using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
150cd16a3f0SFlorian Hahn 
151cd16a3f0SFlorian Hahn   static NodeRef
152e2c43a54SFlorian Hahn   getEntryNode(VPBlockDeepTraversalWrapper<const VPBlockBase *> N) {
153cd16a3f0SFlorian Hahn     return N.getEntry();
154cd16a3f0SFlorian Hahn   }
155cd16a3f0SFlorian Hahn 
156cd16a3f0SFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
157cd16a3f0SFlorian Hahn     return ChildIteratorType(N);
158cd16a3f0SFlorian Hahn   }
159cd16a3f0SFlorian Hahn 
160cd16a3f0SFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
161cd16a3f0SFlorian Hahn     return ChildIteratorType::end(N);
162cd16a3f0SFlorian Hahn   }
163cd16a3f0SFlorian Hahn };
164cd16a3f0SFlorian Hahn 
165655c88caSFlorian Hahn /// Helper for GraphTraits specialization that does not traverses through
166655c88caSFlorian Hahn /// VPRegionBlocks.
167655c88caSFlorian Hahn template <typename BlockTy> class VPBlockShallowTraversalWrapper {
168655c88caSFlorian Hahn   BlockTy Entry;
169655c88caSFlorian Hahn 
170655c88caSFlorian Hahn public:
171655c88caSFlorian Hahn   VPBlockShallowTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
172655c88caSFlorian Hahn   BlockTy getEntry() { return Entry; }
173655c88caSFlorian Hahn };
174655c88caSFlorian Hahn 
175655c88caSFlorian Hahn template <> struct GraphTraits<VPBlockShallowTraversalWrapper<VPBlockBase *>> {
176655c88caSFlorian Hahn   using NodeRef = VPBlockBase *;
177655c88caSFlorian Hahn   using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
178655c88caSFlorian Hahn 
179655c88caSFlorian Hahn   static NodeRef getEntryNode(VPBlockShallowTraversalWrapper<VPBlockBase *> N) {
180655c88caSFlorian Hahn     return N.getEntry();
181655c88caSFlorian Hahn   }
182655c88caSFlorian Hahn 
183655c88caSFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
184655c88caSFlorian Hahn     return N->getSuccessors().begin();
185655c88caSFlorian Hahn   }
186655c88caSFlorian Hahn 
187655c88caSFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
188655c88caSFlorian Hahn     return N->getSuccessors().end();
189655c88caSFlorian Hahn   }
190655c88caSFlorian Hahn };
191655c88caSFlorian Hahn 
192655c88caSFlorian Hahn template <>
193655c88caSFlorian Hahn struct GraphTraits<VPBlockShallowTraversalWrapper<const VPBlockBase *>> {
194655c88caSFlorian Hahn   using NodeRef = const VPBlockBase *;
195655c88caSFlorian Hahn   using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::const_iterator;
196655c88caSFlorian Hahn 
197655c88caSFlorian Hahn   static NodeRef
198655c88caSFlorian Hahn   getEntryNode(VPBlockShallowTraversalWrapper<const VPBlockBase *> N) {
199655c88caSFlorian Hahn     return N.getEntry();
200655c88caSFlorian Hahn   }
201655c88caSFlorian Hahn 
202655c88caSFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
203655c88caSFlorian Hahn     return N->getSuccessors().begin();
204655c88caSFlorian Hahn   }
205655c88caSFlorian Hahn 
206655c88caSFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
207655c88caSFlorian Hahn     return N->getSuccessors().end();
208655c88caSFlorian Hahn   }
209655c88caSFlorian Hahn };
210655c88caSFlorian Hahn 
211655c88caSFlorian Hahn /// Returns an iterator range to traverse the graph starting at \p G in
212655c88caSFlorian Hahn /// depth-first order. The iterator won't traverse through region blocks.
213655c88caSFlorian Hahn inline iterator_range<
214655c88caSFlorian Hahn     df_iterator<VPBlockShallowTraversalWrapper<VPBlockBase *>>>
215655c88caSFlorian Hahn vp_depth_first_shallow(VPBlockBase *G) {
216655c88caSFlorian Hahn   return depth_first(VPBlockShallowTraversalWrapper<VPBlockBase *>(G));
217655c88caSFlorian Hahn }
218655c88caSFlorian Hahn inline iterator_range<
219655c88caSFlorian Hahn     df_iterator<VPBlockShallowTraversalWrapper<const VPBlockBase *>>>
220655c88caSFlorian Hahn vp_depth_first_shallow(const VPBlockBase *G) {
221655c88caSFlorian Hahn   return depth_first(VPBlockShallowTraversalWrapper<const VPBlockBase *>(G));
222655c88caSFlorian Hahn }
223655c88caSFlorian Hahn 
224e2c43a54SFlorian Hahn /// Returns an iterator range to traverse the graph starting at \p G in
225e2c43a54SFlorian Hahn /// depth-first order while traversing through region blocks.
226e2c43a54SFlorian Hahn inline iterator_range<df_iterator<VPBlockDeepTraversalWrapper<VPBlockBase *>>>
227e2c43a54SFlorian Hahn vp_depth_first_deep(VPBlockBase *G) {
228e2c43a54SFlorian Hahn   return depth_first(VPBlockDeepTraversalWrapper<VPBlockBase *>(G));
229e2c43a54SFlorian Hahn }
230e2c43a54SFlorian Hahn inline iterator_range<
231e2c43a54SFlorian Hahn     df_iterator<VPBlockDeepTraversalWrapper<const VPBlockBase *>>>
232e2c43a54SFlorian Hahn vp_depth_first_deep(const VPBlockBase *G) {
233e2c43a54SFlorian Hahn   return depth_first(VPBlockDeepTraversalWrapper<const VPBlockBase *>(G));
234e2c43a54SFlorian Hahn }
235e2c43a54SFlorian Hahn 
236bf9e0da1SFlorian Hahn // The following set of template specializations implement GraphTraits to treat
237bf9e0da1SFlorian Hahn // any VPBlockBase as a node in a graph of VPBlockBases. It's important to note
238bf9e0da1SFlorian Hahn // that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the
239bf9e0da1SFlorian Hahn // VPBlockBase is a VPRegionBlock, this specialization provides access to its
240bf9e0da1SFlorian Hahn // successors/predecessors but not to the blocks inside the region.
241bf9e0da1SFlorian Hahn 
242bf9e0da1SFlorian Hahn template <> struct GraphTraits<VPBlockBase *> {
243bf9e0da1SFlorian Hahn   using NodeRef = VPBlockBase *;
244bf9e0da1SFlorian Hahn   using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
245bf9e0da1SFlorian Hahn 
246bf9e0da1SFlorian Hahn   static NodeRef getEntryNode(NodeRef N) { return N; }
247bf9e0da1SFlorian Hahn 
248bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
249bf9e0da1SFlorian Hahn     return ChildIteratorType(N);
250bf9e0da1SFlorian Hahn   }
251bf9e0da1SFlorian Hahn 
252bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
253bf9e0da1SFlorian Hahn     return ChildIteratorType::end(N);
254bf9e0da1SFlorian Hahn   }
255bf9e0da1SFlorian Hahn };
256bf9e0da1SFlorian Hahn 
257bf9e0da1SFlorian Hahn template <> struct GraphTraits<const VPBlockBase *> {
258bf9e0da1SFlorian Hahn   using NodeRef = const VPBlockBase *;
259bf9e0da1SFlorian Hahn   using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
260bf9e0da1SFlorian Hahn 
261bf9e0da1SFlorian Hahn   static NodeRef getEntryNode(NodeRef N) { return N; }
262bf9e0da1SFlorian Hahn 
263bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
264bf9e0da1SFlorian Hahn     return ChildIteratorType(N);
265bf9e0da1SFlorian Hahn   }
266bf9e0da1SFlorian Hahn 
267bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
268bf9e0da1SFlorian Hahn     return ChildIteratorType::end(N);
269bf9e0da1SFlorian Hahn   }
270bf9e0da1SFlorian Hahn };
271bf9e0da1SFlorian Hahn 
272bf9e0da1SFlorian Hahn /// Inverse graph traits are not implemented yet.
273bf9e0da1SFlorian Hahn /// TODO: Implement a version of VPBlockNonRecursiveTraversalWrapper to traverse
274bf9e0da1SFlorian Hahn /// predecessors recursively through regions.
275bf9e0da1SFlorian Hahn template <> struct GraphTraits<Inverse<VPBlockBase *>> {
276bf9e0da1SFlorian Hahn   using NodeRef = VPBlockBase *;
277bf9e0da1SFlorian Hahn   using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
278bf9e0da1SFlorian Hahn 
279bf9e0da1SFlorian Hahn   static NodeRef getEntryNode(Inverse<NodeRef> B) {
280bf9e0da1SFlorian Hahn     llvm_unreachable("not implemented");
281bf9e0da1SFlorian Hahn   }
282bf9e0da1SFlorian Hahn 
283bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_begin(NodeRef N) {
284bf9e0da1SFlorian Hahn     llvm_unreachable("not implemented");
285bf9e0da1SFlorian Hahn   }
286bf9e0da1SFlorian Hahn 
287bf9e0da1SFlorian Hahn   static inline ChildIteratorType child_end(NodeRef N) {
288bf9e0da1SFlorian Hahn     llvm_unreachable("not implemented");
289bf9e0da1SFlorian Hahn   }
290bf9e0da1SFlorian Hahn };
291bf9e0da1SFlorian Hahn 
292bf9e0da1SFlorian Hahn template <> struct GraphTraits<VPlan *> {
293bf9e0da1SFlorian Hahn   using GraphRef = VPlan *;
294bf9e0da1SFlorian Hahn   using NodeRef = VPBlockBase *;
295bf9e0da1SFlorian Hahn   using nodes_iterator = df_iterator<NodeRef>;
296bf9e0da1SFlorian Hahn 
297bf9e0da1SFlorian Hahn   static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }
298bf9e0da1SFlorian Hahn 
299bf9e0da1SFlorian Hahn   static nodes_iterator nodes_begin(GraphRef N) {
300bf9e0da1SFlorian Hahn     return nodes_iterator::begin(N->getEntry());
301bf9e0da1SFlorian Hahn   }
302bf9e0da1SFlorian Hahn 
303bf9e0da1SFlorian Hahn   static nodes_iterator nodes_end(GraphRef N) {
304bf9e0da1SFlorian Hahn     // df_iterator::end() returns an empty iterator so the node used doesn't
305bf9e0da1SFlorian Hahn     // matter.
306bf9e0da1SFlorian Hahn     return nodes_iterator::end(N->getEntry());
307bf9e0da1SFlorian Hahn   }
308bf9e0da1SFlorian Hahn };
309bf9e0da1SFlorian Hahn 
3104d1959b7SFlorian Hahn inline auto VPlan::getExitBlocks() {
3114d1959b7SFlorian Hahn   VPBlockBase *ScalarHeader = getScalarHeader();
3124d1959b7SFlorian Hahn   return make_filter_range(
3134d1959b7SFlorian Hahn       VPBlockUtils::blocksOnly<VPIRBasicBlock>(
3144d1959b7SFlorian Hahn           vp_depth_first_shallow(getVectorLoopRegion()->getSingleSuccessor())),
3154d1959b7SFlorian Hahn       [ScalarHeader](VPIRBasicBlock *VPIRBB) {
3164d1959b7SFlorian Hahn         return VPIRBB != ScalarHeader && VPIRBB->getNumSuccessors() == 0;
3174d1959b7SFlorian Hahn       });
3184d1959b7SFlorian Hahn }
319cd16a3f0SFlorian Hahn } // namespace llvm
320cd16a3f0SFlorian Hahn 
321cd16a3f0SFlorian Hahn #endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
322