LLVM API Documentation
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