LLVM API Documentation

RegionIterator.h
Go to the documentation of this file.
00001 //===- RegionIterator.h - Iterators to iteratate over Regions ---*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 // This file defines the iterators to iterate over the elements of a Region.
00010 //===----------------------------------------------------------------------===//
00011 #ifndef LLVM_ANALYSIS_REGIONITERATOR_H
00012 #define LLVM_ANALYSIS_REGIONITERATOR_H
00013 
00014 #include "llvm/ADT/GraphTraits.h"
00015 #include "llvm/ADT/PointerIntPair.h"
00016 #include "llvm/ADT/SmallPtrSet.h"
00017 #include "llvm/Analysis/RegionInfo.h"
00018 #include "llvm/IR/CFG.h"
00019 #include "llvm/Support/raw_ostream.h"
00020 
00021 namespace llvm {
00022 //===----------------------------------------------------------------------===//
00023 /// @brief Hierarchical RegionNode successor iterator.
00024 ///
00025 /// This iterator iterates over all successors of a RegionNode.
00026 ///
00027 /// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of
00028 /// the parent Region.  Furthermore for BasicBlocks that start a subregion, a
00029 /// RegionNode representing the subregion is returned.
00030 ///
00031 /// For a subregion RegionNode there is just one successor. The RegionNode
00032 /// representing the exit of the subregion.
00033 template<class NodeType, class BlockT, class RegionT>
00034 class RNSuccIterator : public std::iterator<std::forward_iterator_tag,
00035                                            NodeType, ptrdiff_t> {
00036   typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super;
00037 
00038   typedef GraphTraits<BlockT*> BlockTraits;
00039   typedef typename BlockTraits::ChildIteratorType SuccIterTy;
00040 
00041   // The iterator works in two modes, bb mode or region mode.
00042   enum ItMode {
00043     // In BB mode it returns all successors of this BasicBlock as its
00044     // successors.
00045     ItBB,
00046     // In region mode there is only one successor, thats the regionnode mapping
00047     // to the exit block of the regionnode
00048     ItRgBegin, // At the beginning of the regionnode successor.
00049     ItRgEnd    // At the end of the regionnode successor.
00050   };
00051 
00052   // Use two bit to represent the mode iterator.
00053   PointerIntPair<NodeType*, 2, ItMode> Node;
00054 
00055   // The block successor iterator.
00056   SuccIterTy BItor;
00057 
00058   // advanceRegionSucc - A region node has only one successor. It reaches end
00059   // once we advance it.
00060   void advanceRegionSucc() {
00061     assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!");
00062     Node.setInt(ItRgEnd);
00063   }
00064 
00065   NodeType* getNode() const{ return Node.getPointer(); }
00066 
00067   // isRegionMode - Is the current iterator in region mode?
00068   bool isRegionMode() const { return Node.getInt() != ItBB; }
00069 
00070   // Get the immediate successor. This function may return a Basic Block
00071   // RegionNode or a subregion RegionNode.
00072   NodeType* getISucc(BlockT* BB) const {
00073     NodeType *succ;
00074     succ = getNode()->getParent()->getNode(BB);
00075     assert(succ && "BB not in Region or entered subregion!");
00076     return succ;
00077   }
00078 
00079   // getRegionSucc - Return the successor basic block of a SubRegion RegionNode.
00080   inline BlockT* getRegionSucc() const {
00081     assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!");
00082     return getNode()->template getNodeAs<RegionT>()->getExit();
00083   }
00084 
00085   // isExit - Is this the exit BB of the Region?
00086   inline bool isExit(BlockT* BB) const {
00087     return getNode()->getParent()->getExit() == BB;
00088   }
00089 public:
00090   typedef RNSuccIterator<NodeType, BlockT, RegionT> Self;
00091 
00092   typedef typename super::pointer pointer;
00093 
00094   /// @brief Create begin iterator of a RegionNode.
00095   inline RNSuccIterator(NodeType* node)
00096     : Node(node, node->isSubRegion() ? ItRgBegin : ItBB),
00097       BItor(BlockTraits::child_begin(node->getEntry())) {
00098 
00099     // Skip the exit block
00100     if (!isRegionMode())
00101       while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor))
00102         ++BItor;
00103 
00104     if (isRegionMode() && isExit(getRegionSucc()))
00105       advanceRegionSucc();
00106   }
00107 
00108   /// @brief Create an end iterator.
00109   inline RNSuccIterator(NodeType* node, bool)
00110     : Node(node, node->isSubRegion() ? ItRgEnd : ItBB),
00111       BItor(BlockTraits::child_end(node->getEntry())) {}
00112 
00113   inline bool operator==(const Self& x) const {
00114     assert(isRegionMode() == x.isRegionMode() && "Broken iterator!");
00115     if (isRegionMode())
00116       return Node.getInt() == x.Node.getInt();
00117     else
00118       return BItor == x.BItor;
00119   }
00120 
00121   inline bool operator!=(const Self& x) const { return !operator==(x); }
00122 
00123   inline pointer operator*() const {
00124     BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor;
00125     assert(!isExit(BB) && "Iterator out of range!");
00126     return getISucc(BB);
00127   }
00128 
00129   inline Self& operator++() {
00130     if(isRegionMode()) {
00131       // The Region only has 1 successor.
00132       advanceRegionSucc();
00133     } else {
00134       // Skip the exit.
00135       do
00136         ++BItor;
00137       while (BItor != BlockTraits::child_end(getNode()->getEntry())
00138           && isExit(*BItor));
00139     }
00140     return *this;
00141   }
00142 
00143   inline Self operator++(int) {
00144     Self tmp = *this;
00145     ++*this;
00146     return tmp;
00147   }
00148 
00149   inline const Self &operator=(const Self &I) {
00150     if (this != &I) {
00151       assert(getNode()->getParent() == I.getNode()->getParent()
00152              && "Cannot assign iterators of two different regions!");
00153       Node = I.Node;
00154       BItor = I.BItor;
00155     }
00156     return *this;
00157   }
00158 };
00159 
00160 
00161 //===----------------------------------------------------------------------===//
00162 /// @brief Flat RegionNode iterator.
00163 ///
00164 /// The Flat Region iterator will iterate over all BasicBlock RegionNodes that
00165 /// are contained in the Region and its subregions. This is close to a virtual
00166 /// control flow graph of the Region.
00167 template<class NodeType, class BlockT, class RegionT>
00168 class RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>
00169   : public std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> {
00170   typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super;
00171   typedef GraphTraits<BlockT*> BlockTraits;
00172   typedef typename BlockTraits::ChildIteratorType SuccIterTy;
00173 
00174   NodeType* Node;
00175   SuccIterTy Itor;
00176 
00177 public:
00178   typedef RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT> Self;
00179   typedef typename super::pointer pointer;
00180 
00181   /// @brief Create the iterator from a RegionNode.
00182   ///
00183   /// Note that the incoming node must be a bb node, otherwise it will trigger
00184   /// an assertion when we try to get a BasicBlock.
00185   inline RNSuccIterator(NodeType* node) :
00186     Node(node),
00187     Itor(BlockTraits::child_begin(node->getEntry())) {
00188       assert(!Node->isSubRegion()
00189              && "Subregion node not allowed in flat iterating mode!");
00190       assert(Node->getParent() && "A BB node must have a parent!");
00191 
00192       // Skip the exit block of the iterating region.
00193       while (BlockTraits::child_end(Node->getEntry()) != Itor
00194           && Node->getParent()->getExit() == *Itor)
00195         ++Itor;
00196   }
00197 
00198   /// @brief Create an end iterator
00199   inline RNSuccIterator(NodeType* node, bool) :
00200     Node(node),
00201     Itor(BlockTraits::child_end(node->getEntry())) {
00202       assert(!Node->isSubRegion()
00203              && "Subregion node not allowed in flat iterating mode!");
00204   }
00205 
00206   inline bool operator==(const Self& x) const {
00207     assert(Node->getParent() == x.Node->getParent()
00208            && "Cannot compare iterators of different regions!");
00209 
00210     return Itor == x.Itor && Node == x.Node;
00211   }
00212 
00213   inline bool operator!=(const Self& x) const { return !operator==(x); }
00214 
00215   inline pointer operator*() const {
00216     BlockT *BB = *Itor;
00217 
00218     // Get the iterating region.
00219     RegionT *Parent = Node->getParent();
00220 
00221     // The only case that the successor reaches out of the region is it reaches
00222     // the exit of the region.
00223     assert(Parent->getExit() != BB && "iterator out of range!");
00224 
00225     return Parent->getBBNode(BB);
00226   }
00227 
00228   inline Self& operator++() {
00229     // Skip the exit block of the iterating region.
00230     do
00231       ++Itor;
00232     while (Itor != succ_end(Node->getEntry())
00233         && Node->getParent()->getExit() == *Itor);
00234 
00235     return *this;
00236   }
00237 
00238   inline Self operator++(int) {
00239     Self tmp = *this;
00240     ++*this;
00241     return tmp;
00242   }
00243 
00244   inline const Self &operator=(const Self &I) {
00245     if (this != &I) {
00246       assert(Node->getParent() == I.Node->getParent()
00247              && "Cannot assign iterators to two different regions!");
00248       Node = I.Node;
00249       Itor = I.Itor;
00250     }
00251     return *this;
00252   }
00253 };
00254 
00255 template<class NodeType, class BlockT, class RegionT>
00256 inline RNSuccIterator<NodeType, BlockT, RegionT> succ_begin(NodeType* Node) {
00257   return RNSuccIterator<NodeType, BlockT, RegionT>(Node);
00258 }
00259 
00260 template<class NodeType, class BlockT, class RegionT>
00261 inline RNSuccIterator<NodeType, BlockT, RegionT> succ_end(NodeType* Node) {
00262   return RNSuccIterator<NodeType, BlockT, RegionT>(Node, true);
00263 }
00264 
00265 //===--------------------------------------------------------------------===//
00266 // RegionNode GraphTraits specialization so the bbs in the region can be
00267 // iterate by generic graph iterators.
00268 //
00269 // NodeT can either be region node or const region node, otherwise child_begin
00270 // and child_end fail.
00271 
00272 #define RegionNodeGraphTraits(NodeT, BlockT, RegionT)   \
00273   template<> struct GraphTraits<NodeT*> {      \
00274   typedef NodeT NodeType; \
00275   typedef RNSuccIterator<NodeType, BlockT, RegionT> ChildIteratorType;  \
00276   static NodeType *getEntryNode(NodeType* N) { return N; } \
00277   static inline ChildIteratorType child_begin(NodeType *N) { \
00278     return RNSuccIterator<NodeType, BlockT, RegionT>(N);             \
00279   } \
00280   static inline ChildIteratorType child_end(NodeType *N) { \
00281     return RNSuccIterator<NodeType, BlockT, RegionT>(N, true);     \
00282   } \
00283 }; \
00284 template<> struct GraphTraits<FlatIt<NodeT*>> {  \
00285   typedef NodeT NodeType; \
00286   typedef RNSuccIterator<FlatIt<NodeT>, BlockT, RegionT > ChildIteratorType;    \
00287   static NodeType *getEntryNode(NodeType* N) { return N; } \
00288   static inline ChildIteratorType child_begin(NodeType *N) { \
00289     return RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>(N); \
00290   } \
00291   static inline ChildIteratorType child_end(NodeType *N) { \
00292     return RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>(N, true); \
00293   } \
00294 }
00295 
00296 #define RegionGraphTraits(RegionT, NodeT) \
00297 template<> struct GraphTraits<RegionT*> \
00298   : public GraphTraits<NodeT*> { \
00299   typedef df_iterator<NodeType*> nodes_iterator; \
00300   static NodeType *getEntryNode(RegionT* R) { \
00301     return R->getNode(R->getEntry()); \
00302   } \
00303   static nodes_iterator nodes_begin(RegionT* R) { \
00304     return nodes_iterator::begin(getEntryNode(R)); \
00305   } \
00306   static nodes_iterator nodes_end(RegionT* R) { \
00307     return nodes_iterator::end(getEntryNode(R)); \
00308   } \
00309 }; \
00310 template<> struct GraphTraits<FlatIt<RegionT*> > \
00311   : public GraphTraits<FlatIt<NodeT*> > { \
00312   typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false, \
00313   GraphTraits<FlatIt<NodeType*> > > nodes_iterator; \
00314   static NodeType *getEntryNode(RegionT* R) { \
00315     return R->getBBNode(R->getEntry()); \
00316   } \
00317   static nodes_iterator nodes_begin(RegionT* R) { \
00318     return nodes_iterator::begin(getEntryNode(R)); \
00319   } \
00320   static nodes_iterator nodes_end(RegionT* R) { \
00321     return nodes_iterator::end(getEntryNode(R)); \
00322   } \
00323 }
00324 
00325 RegionNodeGraphTraits(RegionNode, BasicBlock, Region);
00326 RegionNodeGraphTraits(const RegionNode, BasicBlock, Region);
00327 
00328 RegionGraphTraits(Region, RegionNode);
00329 RegionGraphTraits(const Region, const RegionNode);
00330 
00331 template <> struct GraphTraits<RegionInfo*>
00332   : public GraphTraits<FlatIt<RegionNode*> > {
00333   typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false,
00334                       GraphTraits<FlatIt<NodeType*> > > nodes_iterator;
00335 
00336   static NodeType *getEntryNode(RegionInfo *RI) {
00337     return GraphTraits<FlatIt<Region*> >::getEntryNode(RI->getTopLevelRegion());
00338   }
00339   static nodes_iterator nodes_begin(RegionInfo* RI) {
00340     return nodes_iterator::begin(getEntryNode(RI));
00341   }
00342   static nodes_iterator nodes_end(RegionInfo *RI) {
00343     return nodes_iterator::end(getEntryNode(RI));
00344   }
00345 };
00346 
00347 template <> struct GraphTraits<RegionInfoPass*>
00348   : public GraphTraits<RegionInfo *> {
00349   typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false,
00350                       GraphTraits<FlatIt<NodeType*> > > nodes_iterator;
00351 
00352   static NodeType *getEntryNode(RegionInfoPass *RI) {
00353     return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo());
00354   }
00355   static nodes_iterator nodes_begin(RegionInfoPass* RI) {
00356     return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo());
00357   }
00358   static nodes_iterator nodes_end(RegionInfoPass *RI) {
00359     return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo());
00360   }
00361 };
00362 
00363 } // End namespace llvm
00364 
00365 #endif