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