123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- //===- VPlanCFG.h - GraphTraits for VP blocks -------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// Specializations of GraphTraits that allow VPBlockBase graphs to be
- /// treated as proper graphs for generic algorithms;
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
- #define LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
- #include "VPlan.h"
- #include "llvm/ADT/GraphTraits.h"
- #include "llvm/ADT/SmallVector.h"
- namespace llvm {
- //===----------------------------------------------------------------------===//
- // GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs //
- //===----------------------------------------------------------------------===//
- /// Iterator to traverse all successors of a VPBlockBase node. This includes the
- /// entry node of VPRegionBlocks. Exit blocks of a region implicitly have their
- /// parent region's successors. This ensures all blocks in a region are visited
- /// before any blocks in a successor region when doing a reverse post-order
- // traversal of the graph. Region blocks themselves traverse only their entries
- // directly and not their successors. Those will be traversed when a region's
- // exiting block is traversed
- template <typename BlockPtrTy>
- class VPAllSuccessorsIterator
- : public iterator_facade_base<VPAllSuccessorsIterator<BlockPtrTy>,
- std::bidirectional_iterator_tag,
- VPBlockBase> {
- BlockPtrTy Block;
- /// Index of the current successor. For VPBasicBlock nodes, this simply is the
- /// index for the successor array. For VPRegionBlock, SuccessorIdx == 0 is
- /// used for the region's entry block, and SuccessorIdx - 1 are the indices
- /// for the successor array.
- size_t SuccessorIdx;
- static BlockPtrTy getBlockWithSuccs(BlockPtrTy Current) {
- while (Current && Current->getNumSuccessors() == 0)
- Current = Current->getParent();
- return Current;
- }
- /// Templated helper to dereference successor \p SuccIdx of \p Block. Used by
- /// both the const and non-const operator* implementations.
- template <typename T1> static T1 deref(T1 Block, unsigned SuccIdx) {
- if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
- assert(SuccIdx == 0);
- return R->getEntry();
- }
- // For exit blocks, use the next parent region with successors.
- return getBlockWithSuccs(Block)->getSuccessors()[SuccIdx];
- }
- public:
- /// Used by iterator_facade_base with bidirectional_iterator_tag.
- using reference = BlockPtrTy;
- VPAllSuccessorsIterator(BlockPtrTy Block, size_t Idx = 0)
- : Block(Block), SuccessorIdx(Idx) {}
- VPAllSuccessorsIterator(const VPAllSuccessorsIterator &Other)
- : Block(Other.Block), SuccessorIdx(Other.SuccessorIdx) {}
- VPAllSuccessorsIterator &operator=(const VPAllSuccessorsIterator &R) {
- Block = R.Block;
- SuccessorIdx = R.SuccessorIdx;
- return *this;
- }
- static VPAllSuccessorsIterator end(BlockPtrTy Block) {
- if (auto *R = dyn_cast<VPRegionBlock>(Block)) {
- // Traverse through the region's entry node.
- return {R, 1};
- }
- BlockPtrTy ParentWithSuccs = getBlockWithSuccs(Block);
- unsigned NumSuccessors =
- ParentWithSuccs ? ParentWithSuccs->getNumSuccessors() : 0;
- return {Block, NumSuccessors};
- }
- bool operator==(const VPAllSuccessorsIterator &R) const {
- return Block == R.Block && SuccessorIdx == R.SuccessorIdx;
- }
- const VPBlockBase *operator*() const { return deref(Block, SuccessorIdx); }
- BlockPtrTy operator*() { return deref(Block, SuccessorIdx); }
- VPAllSuccessorsIterator &operator++() {
- SuccessorIdx++;
- return *this;
- }
- VPAllSuccessorsIterator &operator--() {
- SuccessorIdx--;
- return *this;
- }
- VPAllSuccessorsIterator operator++(int X) {
- VPAllSuccessorsIterator Orig = *this;
- SuccessorIdx++;
- return Orig;
- }
- };
- /// Helper for GraphTraits specialization that traverses through VPRegionBlocks.
- template <typename BlockTy> class VPBlockDeepTraversalWrapper {
- BlockTy Entry;
- public:
- VPBlockDeepTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
- BlockTy getEntry() { return Entry; }
- };
- /// GraphTraits specialization to recursively traverse VPBlockBase nodes,
- /// including traversing through VPRegionBlocks. Exit blocks of a region
- /// implicitly have their parent region's successors. This ensures all blocks in
- /// a region are visited before any blocks in a successor region when doing a
- /// reverse post-order traversal of the graph.
- template <> struct GraphTraits<VPBlockDeepTraversalWrapper<VPBlockBase *>> {
- using NodeRef = VPBlockBase *;
- using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
- static NodeRef getEntryNode(VPBlockDeepTraversalWrapper<VPBlockBase *> N) {
- return N.getEntry();
- }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return ChildIteratorType(N);
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return ChildIteratorType::end(N);
- }
- };
- template <>
- struct GraphTraits<VPBlockDeepTraversalWrapper<const VPBlockBase *>> {
- using NodeRef = const VPBlockBase *;
- using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
- static NodeRef
- getEntryNode(VPBlockDeepTraversalWrapper<const VPBlockBase *> N) {
- return N.getEntry();
- }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return ChildIteratorType(N);
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return ChildIteratorType::end(N);
- }
- };
- /// Helper for GraphTraits specialization that does not traverses through
- /// VPRegionBlocks.
- template <typename BlockTy> class VPBlockShallowTraversalWrapper {
- BlockTy Entry;
- public:
- VPBlockShallowTraversalWrapper(BlockTy Entry) : Entry(Entry) {}
- BlockTy getEntry() { return Entry; }
- };
- template <> struct GraphTraits<VPBlockShallowTraversalWrapper<VPBlockBase *>> {
- using NodeRef = VPBlockBase *;
- using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
- static NodeRef getEntryNode(VPBlockShallowTraversalWrapper<VPBlockBase *> N) {
- return N.getEntry();
- }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return N->getSuccessors().begin();
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return N->getSuccessors().end();
- }
- };
- template <>
- struct GraphTraits<VPBlockShallowTraversalWrapper<const VPBlockBase *>> {
- using NodeRef = const VPBlockBase *;
- using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::const_iterator;
- static NodeRef
- getEntryNode(VPBlockShallowTraversalWrapper<const VPBlockBase *> N) {
- return N.getEntry();
- }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return N->getSuccessors().begin();
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return N->getSuccessors().end();
- }
- };
- /// Returns an iterator range to traverse the graph starting at \p G in
- /// depth-first order. The iterator won't traverse through region blocks.
- inline iterator_range<
- df_iterator<VPBlockShallowTraversalWrapper<VPBlockBase *>>>
- vp_depth_first_shallow(VPBlockBase *G) {
- return depth_first(VPBlockShallowTraversalWrapper<VPBlockBase *>(G));
- }
- inline iterator_range<
- df_iterator<VPBlockShallowTraversalWrapper<const VPBlockBase *>>>
- vp_depth_first_shallow(const VPBlockBase *G) {
- return depth_first(VPBlockShallowTraversalWrapper<const VPBlockBase *>(G));
- }
- /// Returns an iterator range to traverse the graph starting at \p G in
- /// depth-first order while traversing through region blocks.
- inline iterator_range<df_iterator<VPBlockDeepTraversalWrapper<VPBlockBase *>>>
- vp_depth_first_deep(VPBlockBase *G) {
- return depth_first(VPBlockDeepTraversalWrapper<VPBlockBase *>(G));
- }
- inline iterator_range<
- df_iterator<VPBlockDeepTraversalWrapper<const VPBlockBase *>>>
- vp_depth_first_deep(const VPBlockBase *G) {
- return depth_first(VPBlockDeepTraversalWrapper<const VPBlockBase *>(G));
- }
- // The following set of template specializations implement GraphTraits to treat
- // any VPBlockBase as a node in a graph of VPBlockBases. It's important to note
- // that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the
- // VPBlockBase is a VPRegionBlock, this specialization provides access to its
- // successors/predecessors but not to the blocks inside the region.
- template <> struct GraphTraits<VPBlockBase *> {
- using NodeRef = VPBlockBase *;
- using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;
- static NodeRef getEntryNode(NodeRef N) { return N; }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return ChildIteratorType(N);
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return ChildIteratorType::end(N);
- }
- };
- template <> struct GraphTraits<const VPBlockBase *> {
- using NodeRef = const VPBlockBase *;
- using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;
- static NodeRef getEntryNode(NodeRef N) { return N; }
- static inline ChildIteratorType child_begin(NodeRef N) {
- return ChildIteratorType(N);
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- return ChildIteratorType::end(N);
- }
- };
- /// Inverse graph traits are not implemented yet.
- /// TODO: Implement a version of VPBlockNonRecursiveTraversalWrapper to traverse
- /// predecessors recursively through regions.
- template <> struct GraphTraits<Inverse<VPBlockBase *>> {
- using NodeRef = VPBlockBase *;
- using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;
- static NodeRef getEntryNode(Inverse<NodeRef> B) {
- llvm_unreachable("not implemented");
- }
- static inline ChildIteratorType child_begin(NodeRef N) {
- llvm_unreachable("not implemented");
- }
- static inline ChildIteratorType child_end(NodeRef N) {
- llvm_unreachable("not implemented");
- }
- };
- template <> struct GraphTraits<VPlan *> {
- using GraphRef = VPlan *;
- using NodeRef = VPBlockBase *;
- using nodes_iterator = df_iterator<NodeRef>;
- static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }
- static nodes_iterator nodes_begin(GraphRef N) {
- return nodes_iterator::begin(N->getEntry());
- }
- static nodes_iterator nodes_end(GraphRef N) {
- // df_iterator::end() returns an empty iterator so the node used doesn't
- // matter.
- return nodes_iterator::end(N->getEntry());
- }
- };
- } // namespace llvm
- #endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H
|