VPlanCFG.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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. #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
  12. #define LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
  13. #include "VPlan.h"
  14. #include "llvm/ADT/GraphTraits.h"
  15. #include "llvm/ADT/SmallVector.h"
  16. namespace llvm {
  17. //===----------------------------------------------------------------------===//
  18. // GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs //
  19. //===----------------------------------------------------------------------===//
  20. /// Iterator to traverse all successors of a VPBlockBase node. This includes the
  21. /// entry node of VPRegionBlocks. Exit blocks of a region implicitly have their
  22. /// parent region's successors. This ensures all blocks in a region are visited
  23. /// before any blocks in a successor region when doing a reverse post-order
  24. // traversal of the graph. Region blocks themselves traverse only their entries
  25. // directly and not their successors. Those will be traversed when a region's
  26. // exiting block is traversed
  27. template <typename BlockPtrTy>
  28. class VPAllSuccessorsIterator
  29. : public iterator_facade_base<VPAllSuccessorsIterator<BlockPtrTy>,
  30. std::bidirectional_iterator_tag,
  31. VPBlockBase> {
  32. BlockPtrTy Block;
  33. /// Index of the current successor. For VPBasicBlock nodes, this simply is the
  34. /// index for the successor array. For VPRegionBlock, SuccessorIdx == 0 is
  35. /// used for the region's entry block, and SuccessorIdx - 1 are the indices
  36. /// for the successor array.
  37. size_t SuccessorIdx;
  38. static BlockPtrTy getBlockWithSuccs(BlockPtrTy Current) {
  39. while (Current && Current->getNumSuccessors() == 0)
  40. Current = Current->getParent();
  41. return Current;
  42. }
  43. /// Templated helper to dereference successor \p SuccIdx of \p Block. Used by
  44. /// both the const and non-const operator* implementations.
  45. template <typename T1> static T1 deref(T1 Block, unsigned SuccIdx) {
  46. if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
  47. assert(SuccIdx == 0);
  48. return R->getEntry();
  49. }
  50. // For exit blocks, use the next parent region with successors.
  51. return getBlockWithSuccs(Block)->getSuccessors()[SuccIdx];
  52. }
  53. public:
  54. /// Used by iterator_facade_base with bidirectional_iterator_tag.
  55. using reference = BlockPtrTy;
  56. VPAllSuccessorsIterator(BlockPtrTy Block, size_t Idx = 0)
  57. : Block(Block), SuccessorIdx(Idx) {}
  58. VPAllSuccessorsIterator(const VPAllSuccessorsIterator &Other)
  59. : Block(Other.Block), SuccessorIdx(Other.SuccessorIdx) {}
  60. VPAllSuccessorsIterator &operator=(const VPAllSuccessorsIterator &R) {
  61. Block = R.Block;
  62. SuccessorIdx = R.SuccessorIdx;
  63. return *this;
  64. }
  65. static VPAllSuccessorsIterator end(BlockPtrTy Block) {
  66. if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
  67. // Traverse through the region's entry node.
  68. return {R, 1};
  69. }
  70. BlockPtrTy ParentWithSuccs = getBlockWithSuccs(Block);
  71. unsigned NumSuccessors =
  72. ParentWithSuccs ? ParentWithSuccs->getNumSuccessors() : 0;
  73. return {Block, NumSuccessors};
  74. }
  75. bool operator==(const VPAllSuccessorsIterator &R) const {
  76. return Block == R.Block && SuccessorIdx == R.SuccessorIdx;
  77. }
  78. const VPBlockBase *operator*() const { return deref(Block, SuccessorIdx); }
  79. BlockPtrTy operator*() { return deref(Block, SuccessorIdx); }
  80. VPAllSuccessorsIterator &operator++() {
  81. SuccessorIdx++;
  82. return *this;
  83. }
  84. VPAllSuccessorsIterator &operator--() {
  85. SuccessorIdx--;
  86. return *this;
  87. }
  88. VPAllSuccessorsIterator operator++(int X) {
  89. VPAllSuccessorsIterator Orig = *this;
  90. SuccessorIdx++;
  91. return Orig;
  92. }
  93. };
  94. /// Helper for GraphTraits specialization that traverses through VPRegionBlocks.
  95. template <typename BlockTy> class VPBlockDeepTraversalWrapper {
  96. BlockTy Entry;
  97. public:
  98. VPBlockDeepTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
  99. BlockTy getEntry() { return Entry; }
  100. };
  101. /// GraphTraits specialization to recursively traverse VPBlockBase nodes,
  102. /// including traversing through VPRegionBlocks. Exit blocks of a region
  103. /// implicitly have their parent region's successors. This ensures all blocks in
  104. /// a region are visited before any blocks in a successor region when doing a
  105. /// reverse post-order traversal of the graph.
  106. template <> struct GraphTraits<VPBlockDeepTraversalWrapper<VPBlockBase *>> {
  107. using NodeRef = VPBlockBase *;
  108. using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
  109. static NodeRef getEntryNode(VPBlockDeepTraversalWrapper<VPBlockBase *> N) {
  110. return N.getEntry();
  111. }
  112. static inline ChildIteratorType child_begin(NodeRef N) {
  113. return ChildIteratorType(N);
  114. }
  115. static inline ChildIteratorType child_end(NodeRef N) {
  116. return ChildIteratorType::end(N);
  117. }
  118. };
  119. template <>
  120. struct GraphTraits<VPBlockDeepTraversalWrapper<const VPBlockBase *>> {
  121. using NodeRef = const VPBlockBase *;
  122. using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
  123. static NodeRef
  124. getEntryNode(VPBlockDeepTraversalWrapper<const VPBlockBase *> N) {
  125. return N.getEntry();
  126. }
  127. static inline ChildIteratorType child_begin(NodeRef N) {
  128. return ChildIteratorType(N);
  129. }
  130. static inline ChildIteratorType child_end(NodeRef N) {
  131. return ChildIteratorType::end(N);
  132. }
  133. };
  134. /// Helper for GraphTraits specialization that does not traverses through
  135. /// VPRegionBlocks.
  136. template <typename BlockTy> class VPBlockShallowTraversalWrapper {
  137. BlockTy Entry;
  138. public:
  139. VPBlockShallowTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
  140. BlockTy getEntry() { return Entry; }
  141. };
  142. template <> struct GraphTraits<VPBlockShallowTraversalWrapper<VPBlockBase *>> {
  143. using NodeRef = VPBlockBase *;
  144. using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
  145. static NodeRef getEntryNode(VPBlockShallowTraversalWrapper<VPBlockBase *> N) {
  146. return N.getEntry();
  147. }
  148. static inline ChildIteratorType child_begin(NodeRef N) {
  149. return N->getSuccessors().begin();
  150. }
  151. static inline ChildIteratorType child_end(NodeRef N) {
  152. return N->getSuccessors().end();
  153. }
  154. };
  155. template <>
  156. struct GraphTraits<VPBlockShallowTraversalWrapper<const VPBlockBase *>> {
  157. using NodeRef = const VPBlockBase *;
  158. using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::const_iterator;
  159. static NodeRef
  160. getEntryNode(VPBlockShallowTraversalWrapper<const VPBlockBase *> N) {
  161. return N.getEntry();
  162. }
  163. static inline ChildIteratorType child_begin(NodeRef N) {
  164. return N->getSuccessors().begin();
  165. }
  166. static inline ChildIteratorType child_end(NodeRef N) {
  167. return N->getSuccessors().end();
  168. }
  169. };
  170. /// Returns an iterator range to traverse the graph starting at \p G in
  171. /// depth-first order. The iterator won't traverse through region blocks.
  172. inline iterator_range<
  173. df_iterator<VPBlockShallowTraversalWrapper<VPBlockBase *>>>
  174. vp_depth_first_shallow(VPBlockBase *G) {
  175. return depth_first(VPBlockShallowTraversalWrapper<VPBlockBase *>(G));
  176. }
  177. inline iterator_range<
  178. df_iterator<VPBlockShallowTraversalWrapper<const VPBlockBase *>>>
  179. vp_depth_first_shallow(const VPBlockBase *G) {
  180. return depth_first(VPBlockShallowTraversalWrapper<const VPBlockBase *>(G));
  181. }
  182. /// Returns an iterator range to traverse the graph starting at \p G in
  183. /// depth-first order while traversing through region blocks.
  184. inline iterator_range<df_iterator<VPBlockDeepTraversalWrapper<VPBlockBase *>>>
  185. vp_depth_first_deep(VPBlockBase *G) {
  186. return depth_first(VPBlockDeepTraversalWrapper<VPBlockBase *>(G));
  187. }
  188. inline iterator_range<
  189. df_iterator<VPBlockDeepTraversalWrapper<const VPBlockBase *>>>
  190. vp_depth_first_deep(const VPBlockBase *G) {
  191. return depth_first(VPBlockDeepTraversalWrapper<const VPBlockBase *>(G));
  192. }
  193. // The following set of template specializations implement GraphTraits to treat
  194. // any VPBlockBase as a node in a graph of VPBlockBases. It's important to note
  195. // that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the
  196. // VPBlockBase is a VPRegionBlock, this specialization provides access to its
  197. // successors/predecessors but not to the blocks inside the region.
  198. template <> struct GraphTraits<VPBlockBase *> {
  199. using NodeRef = VPBlockBase *;
  200. using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
  201. static NodeRef getEntryNode(NodeRef N) { return N; }
  202. static inline ChildIteratorType child_begin(NodeRef N) {
  203. return ChildIteratorType(N);
  204. }
  205. static inline ChildIteratorType child_end(NodeRef N) {
  206. return ChildIteratorType::end(N);
  207. }
  208. };
  209. template <> struct GraphTraits<const VPBlockBase *> {
  210. using NodeRef = const VPBlockBase *;
  211. using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
  212. static NodeRef getEntryNode(NodeRef N) { return N; }
  213. static inline ChildIteratorType child_begin(NodeRef N) {
  214. return ChildIteratorType(N);
  215. }
  216. static inline ChildIteratorType child_end(NodeRef N) {
  217. return ChildIteratorType::end(N);
  218. }
  219. };
  220. /// Inverse graph traits are not implemented yet.
  221. /// TODO: Implement a version of VPBlockNonRecursiveTraversalWrapper to traverse
  222. /// predecessors recursively through regions.
  223. template <> struct GraphTraits<Inverse<VPBlockBase *>> {
  224. using NodeRef = VPBlockBase *;
  225. using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
  226. static NodeRef getEntryNode(Inverse<NodeRef> B) {
  227. llvm_unreachable("not implemented");
  228. }
  229. static inline ChildIteratorType child_begin(NodeRef N) {
  230. llvm_unreachable("not implemented");
  231. }
  232. static inline ChildIteratorType child_end(NodeRef N) {
  233. llvm_unreachable("not implemented");
  234. }
  235. };
  236. template <> struct GraphTraits<VPlan *> {
  237. using GraphRef = VPlan *;
  238. using NodeRef = VPBlockBase *;
  239. using nodes_iterator = df_iterator<NodeRef>;
  240. static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }
  241. static nodes_iterator nodes_begin(GraphRef N) {
  242. return nodes_iterator::begin(N->getEntry());
  243. }
  244. static nodes_iterator nodes_end(GraphRef N) {
  245. // df_iterator::end() returns an empty iterator so the node used doesn't
  246. // matter.
  247. return nodes_iterator::end(N->getEntry());
  248. }
  249. };
  250. } // namespace llvm
  251. #endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H