Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlanCFG.h
35269 views
//===- VPlanCFG.h - GraphTraits for VP blocks -------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// Specializations of GraphTraits that allow VPBlockBase graphs to be8/// treated as proper graphs for generic algorithms;9//===----------------------------------------------------------------------===//1011#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H12#define LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H1314#include "VPlan.h"15#include "llvm/ADT/DepthFirstIterator.h"16#include "llvm/ADT/GraphTraits.h"17#include "llvm/ADT/SmallVector.h"1819namespace llvm {2021//===----------------------------------------------------------------------===//22// GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs //23//===----------------------------------------------------------------------===//2425/// Iterator to traverse all successors of a VPBlockBase node. This includes the26/// entry node of VPRegionBlocks. Exit blocks of a region implicitly have their27/// parent region's successors. This ensures all blocks in a region are visited28/// before any blocks in a successor region when doing a reverse post-order29// traversal of the graph. Region blocks themselves traverse only their entries30// directly and not their successors. Those will be traversed when a region's31// exiting block is traversed32template <typename BlockPtrTy>33class VPAllSuccessorsIterator34: public iterator_facade_base<VPAllSuccessorsIterator<BlockPtrTy>,35std::bidirectional_iterator_tag,36VPBlockBase> {37BlockPtrTy Block;38/// Index of the current successor. For VPBasicBlock nodes, this simply is the39/// index for the successor array. For VPRegionBlock, SuccessorIdx == 0 is40/// used for the region's entry block, and SuccessorIdx - 1 are the indices41/// for the successor array.42size_t SuccessorIdx;4344static BlockPtrTy getBlockWithSuccs(BlockPtrTy Current) {45while (Current && Current->getNumSuccessors() == 0)46Current = Current->getParent();47return Current;48}4950/// Templated helper to dereference successor \p SuccIdx of \p Block. Used by51/// both the const and non-const operator* implementations.52template <typename T1> static T1 deref(T1 Block, unsigned SuccIdx) {53if (auto *R = dyn_cast<VPRegionBlock>(Block)) {54assert(SuccIdx == 0);55return R->getEntry();56}5758// For exit blocks, use the next parent region with successors.59return getBlockWithSuccs(Block)->getSuccessors()[SuccIdx];60}6162public:63/// Used by iterator_facade_base with bidirectional_iterator_tag.64using reference = BlockPtrTy;6566VPAllSuccessorsIterator(BlockPtrTy Block, size_t Idx = 0)67: Block(Block), SuccessorIdx(Idx) {}68VPAllSuccessorsIterator(const VPAllSuccessorsIterator &Other)69: Block(Other.Block), SuccessorIdx(Other.SuccessorIdx) {}7071VPAllSuccessorsIterator &operator=(const VPAllSuccessorsIterator &R) {72Block = R.Block;73SuccessorIdx = R.SuccessorIdx;74return *this;75}7677static VPAllSuccessorsIterator end(BlockPtrTy Block) {78if (auto *R = dyn_cast<VPRegionBlock>(Block)) {79// Traverse through the region's entry node.80return {R, 1};81}82BlockPtrTy ParentWithSuccs = getBlockWithSuccs(Block);83unsigned NumSuccessors =84ParentWithSuccs ? ParentWithSuccs->getNumSuccessors() : 0;85return {Block, NumSuccessors};86}8788bool operator==(const VPAllSuccessorsIterator &R) const {89return Block == R.Block && SuccessorIdx == R.SuccessorIdx;90}9192const VPBlockBase *operator*() const { return deref(Block, SuccessorIdx); }9394BlockPtrTy operator*() { return deref(Block, SuccessorIdx); }9596VPAllSuccessorsIterator &operator++() {97SuccessorIdx++;98return *this;99}100101VPAllSuccessorsIterator &operator--() {102SuccessorIdx--;103return *this;104}105106VPAllSuccessorsIterator operator++(int X) {107VPAllSuccessorsIterator Orig = *this;108SuccessorIdx++;109return Orig;110}111};112113/// Helper for GraphTraits specialization that traverses through VPRegionBlocks.114template <typename BlockTy> class VPBlockDeepTraversalWrapper {115BlockTy Entry;116117public:118VPBlockDeepTraversalWrapper(BlockTy Entry) : Entry(Entry) {}119BlockTy getEntry() { return Entry; }120};121122/// GraphTraits specialization to recursively traverse VPBlockBase nodes,123/// including traversing through VPRegionBlocks. Exit blocks of a region124/// implicitly have their parent region's successors. This ensures all blocks in125/// a region are visited before any blocks in a successor region when doing a126/// reverse post-order traversal of the graph.127template <> struct GraphTraits<VPBlockDeepTraversalWrapper<VPBlockBase *>> {128using NodeRef = VPBlockBase *;129using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;130131static NodeRef getEntryNode(VPBlockDeepTraversalWrapper<VPBlockBase *> N) {132return N.getEntry();133}134135static inline ChildIteratorType child_begin(NodeRef N) {136return ChildIteratorType(N);137}138139static inline ChildIteratorType child_end(NodeRef N) {140return ChildIteratorType::end(N);141}142};143144template <>145struct GraphTraits<VPBlockDeepTraversalWrapper<const VPBlockBase *>> {146using NodeRef = const VPBlockBase *;147using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;148149static NodeRef150getEntryNode(VPBlockDeepTraversalWrapper<const VPBlockBase *> N) {151return N.getEntry();152}153154static inline ChildIteratorType child_begin(NodeRef N) {155return ChildIteratorType(N);156}157158static inline ChildIteratorType child_end(NodeRef N) {159return ChildIteratorType::end(N);160}161};162163/// Helper for GraphTraits specialization that does not traverses through164/// VPRegionBlocks.165template <typename BlockTy> class VPBlockShallowTraversalWrapper {166BlockTy Entry;167168public:169VPBlockShallowTraversalWrapper(BlockTy Entry) : Entry(Entry) {}170BlockTy getEntry() { return Entry; }171};172173template <> struct GraphTraits<VPBlockShallowTraversalWrapper<VPBlockBase *>> {174using NodeRef = VPBlockBase *;175using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;176177static NodeRef getEntryNode(VPBlockShallowTraversalWrapper<VPBlockBase *> N) {178return N.getEntry();179}180181static inline ChildIteratorType child_begin(NodeRef N) {182return N->getSuccessors().begin();183}184185static inline ChildIteratorType child_end(NodeRef N) {186return N->getSuccessors().end();187}188};189190template <>191struct GraphTraits<VPBlockShallowTraversalWrapper<const VPBlockBase *>> {192using NodeRef = const VPBlockBase *;193using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::const_iterator;194195static NodeRef196getEntryNode(VPBlockShallowTraversalWrapper<const VPBlockBase *> N) {197return N.getEntry();198}199200static inline ChildIteratorType child_begin(NodeRef N) {201return N->getSuccessors().begin();202}203204static inline ChildIteratorType child_end(NodeRef N) {205return N->getSuccessors().end();206}207};208209/// Returns an iterator range to traverse the graph starting at \p G in210/// depth-first order. The iterator won't traverse through region blocks.211inline iterator_range<212df_iterator<VPBlockShallowTraversalWrapper<VPBlockBase *>>>213vp_depth_first_shallow(VPBlockBase *G) {214return depth_first(VPBlockShallowTraversalWrapper<VPBlockBase *>(G));215}216inline iterator_range<217df_iterator<VPBlockShallowTraversalWrapper<const VPBlockBase *>>>218vp_depth_first_shallow(const VPBlockBase *G) {219return depth_first(VPBlockShallowTraversalWrapper<const VPBlockBase *>(G));220}221222/// Returns an iterator range to traverse the graph starting at \p G in223/// depth-first order while traversing through region blocks.224inline iterator_range<df_iterator<VPBlockDeepTraversalWrapper<VPBlockBase *>>>225vp_depth_first_deep(VPBlockBase *G) {226return depth_first(VPBlockDeepTraversalWrapper<VPBlockBase *>(G));227}228inline iterator_range<229df_iterator<VPBlockDeepTraversalWrapper<const VPBlockBase *>>>230vp_depth_first_deep(const VPBlockBase *G) {231return depth_first(VPBlockDeepTraversalWrapper<const VPBlockBase *>(G));232}233234// The following set of template specializations implement GraphTraits to treat235// any VPBlockBase as a node in a graph of VPBlockBases. It's important to note236// that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the237// VPBlockBase is a VPRegionBlock, this specialization provides access to its238// successors/predecessors but not to the blocks inside the region.239240template <> struct GraphTraits<VPBlockBase *> {241using NodeRef = VPBlockBase *;242using ChildIteratorType = VPAllSuccessorsIterator<VPBlockBase *>;243244static NodeRef getEntryNode(NodeRef N) { return N; }245246static inline ChildIteratorType child_begin(NodeRef N) {247return ChildIteratorType(N);248}249250static inline ChildIteratorType child_end(NodeRef N) {251return ChildIteratorType::end(N);252}253};254255template <> struct GraphTraits<const VPBlockBase *> {256using NodeRef = const VPBlockBase *;257using ChildIteratorType = VPAllSuccessorsIterator<const VPBlockBase *>;258259static NodeRef getEntryNode(NodeRef N) { return N; }260261static inline ChildIteratorType child_begin(NodeRef N) {262return ChildIteratorType(N);263}264265static inline ChildIteratorType child_end(NodeRef N) {266return ChildIteratorType::end(N);267}268};269270/// Inverse graph traits are not implemented yet.271/// TODO: Implement a version of VPBlockNonRecursiveTraversalWrapper to traverse272/// predecessors recursively through regions.273template <> struct GraphTraits<Inverse<VPBlockBase *>> {274using NodeRef = VPBlockBase *;275using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;276277static NodeRef getEntryNode(Inverse<NodeRef> B) {278llvm_unreachable("not implemented");279}280281static inline ChildIteratorType child_begin(NodeRef N) {282llvm_unreachable("not implemented");283}284285static inline ChildIteratorType child_end(NodeRef N) {286llvm_unreachable("not implemented");287}288};289290template <> struct GraphTraits<VPlan *> {291using GraphRef = VPlan *;292using NodeRef = VPBlockBase *;293using nodes_iterator = df_iterator<NodeRef>;294295static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }296297static nodes_iterator nodes_begin(GraphRef N) {298return nodes_iterator::begin(N->getEntry());299}300301static nodes_iterator nodes_end(GraphRef N) {302// df_iterator::end() returns an empty iterator so the node used doesn't303// matter.304return nodes_iterator::end(N->getEntry());305}306};307308} // namespace llvm309310#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H311312313