Viewing file: RegionIterator.h (14.11 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- RegionIterator.h - Iterators to iteratate over Regions ---*- 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 // //===----------------------------------------------------------------------===// // This file defines the iterators to iterate over the elements of a Region. //===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_REGIONITERATOR_H #define LLVM_ANALYSIS_REGIONITERATOR_H
#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Analysis/RegionInfo.h" #include <cassert> #include <iterator> #include <type_traits>
namespace llvm {
class BasicBlock; class RegionInfo;
//===----------------------------------------------------------------------===// /// Hierarchical RegionNode successor iterator. /// /// This iterator iterates over all successors of a RegionNode. /// /// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of /// the parent Region. Furthermore for BasicBlocks that start a subregion, a /// RegionNode representing the subregion is returned. /// /// For a subregion RegionNode there is just one successor. The RegionNode /// representing the exit of the subregion. template <class NodeRef, class BlockT, class RegionT> class RNSuccIterator { public: using iterator_category = std::forward_iterator_tag; using value_type = NodeRef; using difference_type = std::ptrdiff_t; using pointer = value_type *; using reference = value_type &;
private: using BlockTraits = GraphTraits<BlockT *>; using SuccIterTy = typename BlockTraits::ChildIteratorType;
// The iterator works in two modes, bb mode or region mode. enum ItMode { // In BB mode it returns all successors of this BasicBlock as its // successors. ItBB, // In region mode there is only one successor, thats the regionnode mapping // to the exit block of the regionnode ItRgBegin, // At the beginning of the regionnode successor. ItRgEnd // At the end of the regionnode successor. };
static_assert(std::is_pointer<NodeRef>::value, "FIXME: Currently RNSuccIterator only supports NodeRef as " "pointers due to the use of pointer-specific data structures " "(e.g. PointerIntPair and SmallPtrSet) internally. Generalize " "it to support non-pointer types");
// Use two bit to represent the mode iterator. PointerIntPair<NodeRef, 2, ItMode> Node;
// The block successor iterator. SuccIterTy BItor;
// advanceRegionSucc - A region node has only one successor. It reaches end // once we advance it. void advanceRegionSucc() { assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!"); Node.setInt(ItRgEnd); }
NodeRef getNode() const { return Node.getPointer(); }
// isRegionMode - Is the current iterator in region mode? bool isRegionMode() const { return Node.getInt() != ItBB; }
// Get the immediate successor. This function may return a Basic Block // RegionNode or a subregion RegionNode. NodeRef getISucc(BlockT *BB) const { NodeRef succ; succ = getNode()->getParent()->getNode(BB); assert(succ && "BB not in Region or entered subregion!"); return succ; }
// getRegionSucc - Return the successor basic block of a SubRegion RegionNode. inline BlockT* getRegionSucc() const { assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!"); return getNode()->template getNodeAs<RegionT>()->getExit(); }
// isExit - Is this the exit BB of the Region? inline bool isExit(BlockT* BB) const { return getNode()->getParent()->getExit() == BB; }
public: using Self = RNSuccIterator<NodeRef, BlockT, RegionT>;
/// Create begin iterator of a RegionNode. inline RNSuccIterator(NodeRef node) : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), BItor(BlockTraits::child_begin(node->getEntry())) { // Skip the exit block if (!isRegionMode()) while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor)) ++BItor;
if (isRegionMode() && isExit(getRegionSucc())) advanceRegionSucc(); }
/// Create an end iterator. inline RNSuccIterator(NodeRef node, bool) : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), BItor(BlockTraits::child_end(node->getEntry())) {}
inline bool operator==(const Self& x) const { assert(isRegionMode() == x.isRegionMode() && "Broken iterator!"); if (isRegionMode()) return Node.getInt() == x.Node.getInt(); else return BItor == x.BItor; }
inline bool operator!=(const Self& x) const { return !operator==(x); }
inline value_type operator*() const { BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor; assert(!isExit(BB) && "Iterator out of range!"); return getISucc(BB); }
inline Self& operator++() { if(isRegionMode()) { // The Region only has 1 successor. advanceRegionSucc(); } else { // Skip the exit. do ++BItor; while (BItor != BlockTraits::child_end(getNode()->getEntry()) && isExit(*BItor)); } return *this; }
inline Self operator++(int) { Self tmp = *this; ++*this; return tmp; } };
//===----------------------------------------------------------------------===// /// Flat RegionNode iterator. /// /// The Flat Region iterator will iterate over all BasicBlock RegionNodes that /// are contained in the Region and its subregions. This is close to a virtual /// control flow graph of the Region. template <class NodeRef, class BlockT, class RegionT> class RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT> { using BlockTraits = GraphTraits<BlockT *>; using SuccIterTy = typename BlockTraits::ChildIteratorType;
NodeRef Node; SuccIterTy Itor;
public: using iterator_category = std::forward_iterator_tag; using value_type = NodeRef; using difference_type = std::ptrdiff_t; using pointer = value_type *; using reference = value_type &;
using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>;
/// Create the iterator from a RegionNode. /// /// Note that the incoming node must be a bb node, otherwise it will trigger /// an assertion when we try to get a BasicBlock. inline RNSuccIterator(NodeRef node) : Node(node), Itor(BlockTraits::child_begin(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); assert(Node->getParent() && "A BB node must have a parent!");
// Skip the exit block of the iterating region. while (BlockTraits::child_end(Node->getEntry()) != Itor && Node->getParent()->getExit() == *Itor) ++Itor; }
/// Create an end iterator inline RNSuccIterator(NodeRef node, bool) : Node(node), Itor(BlockTraits::child_end(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); }
inline bool operator==(const Self& x) const { assert(Node->getParent() == x.Node->getParent() && "Cannot compare iterators of different regions!");
return Itor == x.Itor && Node == x.Node; }
inline bool operator!=(const Self& x) const { return !operator==(x); }
inline value_type operator*() const { BlockT *BB = *Itor;
// Get the iterating region. RegionT *Parent = Node->getParent();
// The only case that the successor reaches out of the region is it reaches // the exit of the region. assert(Parent->getExit() != BB && "iterator out of range!");
return Parent->getBBNode(BB); }
inline Self& operator++() { // Skip the exit block of the iterating region. do ++Itor; while (Itor != succ_end(Node->getEntry()) && Node->getParent()->getExit() == *Itor);
return *this; }
inline Self operator++(int) { Self tmp = *this; ++*this; return tmp; } };
template <class NodeRef, class BlockT, class RegionT> inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_begin(NodeRef Node) { return RNSuccIterator<NodeRef, BlockT, RegionT>(Node); }
template <class NodeRef, class BlockT, class RegionT> inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) { return RNSuccIterator<NodeRef, BlockT, RegionT>(Node, true); }
//===--------------------------------------------------------------------===// // RegionNode GraphTraits specialization so the bbs in the region can be // iterate by generic graph iterators. // // NodeT can either be region node or const region node, otherwise child_begin // and child_end fail.
#define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \ template <> struct GraphTraits<NodeT *> { \ using NodeRef = NodeT *; \ using ChildIteratorType = RNSuccIterator<NodeRef, BlockT, RegionT>; \ static NodeRef getEntryNode(NodeRef N) { return N; } \ static inline ChildIteratorType child_begin(NodeRef N) { \ return RNSuccIterator<NodeRef, BlockT, RegionT>(N); \ } \ static inline ChildIteratorType child_end(NodeRef N) { \ return RNSuccIterator<NodeRef, BlockT, RegionT>(N, true); \ } \ }; \ template <> struct GraphTraits<FlatIt<NodeT *>> { \ using NodeRef = NodeT *; \ using ChildIteratorType = \ RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>; \ static NodeRef getEntryNode(NodeRef N) { return N; } \ static inline ChildIteratorType child_begin(NodeRef N) { \ return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N); \ } \ static inline ChildIteratorType child_end(NodeRef N) { \ return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N, true); \ } \ }
#define RegionGraphTraits(RegionT, NodeT) \ template <> struct GraphTraits<RegionT *> : public GraphTraits<NodeT *> { \ using nodes_iterator = df_iterator<NodeRef>; \ static NodeRef getEntryNode(RegionT *R) { \ return R->getNode(R->getEntry()); \ } \ static nodes_iterator nodes_begin(RegionT *R) { \ return nodes_iterator::begin(getEntryNode(R)); \ } \ static nodes_iterator nodes_end(RegionT *R) { \ return nodes_iterator::end(getEntryNode(R)); \ } \ }; \ template <> \ struct GraphTraits<FlatIt<RegionT *>> \ : public GraphTraits<FlatIt<NodeT *>> { \ using nodes_iterator = \ df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, \ GraphTraits<FlatIt<NodeRef>>>; \ static NodeRef getEntryNode(RegionT *R) { \ return R->getBBNode(R->getEntry()); \ } \ static nodes_iterator nodes_begin(RegionT *R) { \ return nodes_iterator::begin(getEntryNode(R)); \ } \ static nodes_iterator nodes_end(RegionT *R) { \ return nodes_iterator::end(getEntryNode(R)); \ } \ }
RegionNodeGraphTraits(RegionNode, BasicBlock, Region); RegionNodeGraphTraits(const RegionNode, BasicBlock, Region);
RegionGraphTraits(Region, RegionNode); RegionGraphTraits(const Region, const RegionNode);
template <> struct GraphTraits<RegionInfo*> : public GraphTraits<FlatIt<RegionNode*>> { using nodes_iterator = df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, GraphTraits<FlatIt<NodeRef>>>;
static NodeRef getEntryNode(RegionInfo *RI) { return GraphTraits<FlatIt<Region*>>::getEntryNode(RI->getTopLevelRegion()); }
static nodes_iterator nodes_begin(RegionInfo* RI) { return nodes_iterator::begin(getEntryNode(RI)); }
static nodes_iterator nodes_end(RegionInfo *RI) { return nodes_iterator::end(getEntryNode(RI)); } };
template <> struct GraphTraits<RegionInfoPass*> : public GraphTraits<RegionInfo *> { using nodes_iterator = df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, GraphTraits<FlatIt<NodeRef>>>;
static NodeRef getEntryNode(RegionInfoPass *RI) { return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo()); }
static nodes_iterator nodes_begin(RegionInfoPass* RI) { return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo()); }
static nodes_iterator nodes_end(RegionInfoPass *RI) { return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo()); } };
} // end namespace llvm
#endif // LLVM_ANALYSIS_REGIONITERATOR_H
|