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