LLVM API Documentation
00001 //===--------- LoopIterator.h - Iterate over loop blocks --------*- 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 iterators to visit the basic blocks within a loop. 00010 // 00011 // These iterators currently visit blocks within subloops as well. 00012 // Unfortunately we have no efficient way of summarizing loop exits which would 00013 // allow skipping subloops during traversal. 00014 // 00015 // If you want to visit all blocks in a loop and don't need an ordered traveral, 00016 // use Loop::block_begin() instead. 00017 // 00018 // This is intentionally designed to work with ill-formed loops in which the 00019 // backedge has been deleted. The only prerequisite is that all blocks 00020 // contained within the loop according to the most recent LoopInfo analysis are 00021 // reachable from the loop header. 00022 //===----------------------------------------------------------------------===// 00023 00024 #ifndef LLVM_ANALYSIS_LOOPITERATOR_H 00025 #define LLVM_ANALYSIS_LOOPITERATOR_H 00026 00027 #include "llvm/ADT/PostOrderIterator.h" 00028 #include "llvm/Analysis/LoopInfo.h" 00029 00030 namespace llvm { 00031 00032 class LoopBlocksTraversal; 00033 00034 /// Store the result of a depth first search within basic blocks contained by a 00035 /// single loop. 00036 /// 00037 /// TODO: This could be generalized for any CFG region, or the entire CFG. 00038 class LoopBlocksDFS { 00039 public: 00040 /// Postorder list iterators. 00041 typedef std::vector<BasicBlock*>::const_iterator POIterator; 00042 typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator; 00043 00044 friend class LoopBlocksTraversal; 00045 00046 private: 00047 Loop *L; 00048 00049 /// Map each block to its postorder number. A block is only mapped after it is 00050 /// preorder visited by DFS. It's postorder number is initially zero and set 00051 /// to nonzero after it is finished by postorder traversal. 00052 DenseMap<BasicBlock*, unsigned> PostNumbers; 00053 std::vector<BasicBlock*> PostBlocks; 00054 00055 public: 00056 LoopBlocksDFS(Loop *Container) : 00057 L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) { 00058 PostBlocks.reserve(Container->getNumBlocks()); 00059 } 00060 00061 Loop *getLoop() const { return L; } 00062 00063 /// Traverse the loop blocks and store the DFS result. 00064 void perform(LoopInfo *LI); 00065 00066 /// Return true if postorder numbers are assigned to all loop blocks. 00067 bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); } 00068 00069 /// Iterate over the cached postorder blocks. 00070 POIterator beginPostorder() const { 00071 assert(isComplete() && "bad loop DFS"); 00072 return PostBlocks.begin(); 00073 } 00074 POIterator endPostorder() const { return PostBlocks.end(); } 00075 00076 /// Reverse iterate over the cached postorder blocks. 00077 RPOIterator beginRPO() const { 00078 assert(isComplete() && "bad loop DFS"); 00079 return PostBlocks.rbegin(); 00080 } 00081 RPOIterator endRPO() const { return PostBlocks.rend(); } 00082 00083 /// Return true if this block has been preorder visited. 00084 bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); } 00085 00086 /// Return true if this block has a postorder number. 00087 bool hasPostorder(BasicBlock *BB) const { 00088 DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB); 00089 return I != PostNumbers.end() && I->second; 00090 } 00091 00092 /// Get a block's postorder number. 00093 unsigned getPostorder(BasicBlock *BB) const { 00094 DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB); 00095 assert(I != PostNumbers.end() && "block not visited by DFS"); 00096 assert(I->second && "block not finished by DFS"); 00097 return I->second; 00098 } 00099 00100 /// Get a block's reverse postorder number. 00101 unsigned getRPO(BasicBlock *BB) const { 00102 return 1 + PostBlocks.size() - getPostorder(BB); 00103 } 00104 00105 void clear() { 00106 PostNumbers.clear(); 00107 PostBlocks.clear(); 00108 } 00109 }; 00110 00111 /// Specialize po_iterator_storage to record postorder numbers. 00112 template<> class po_iterator_storage<LoopBlocksTraversal, true> { 00113 LoopBlocksTraversal &LBT; 00114 public: 00115 po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {} 00116 // These functions are defined below. 00117 bool insertEdge(BasicBlock *From, BasicBlock *To); 00118 void finishPostorder(BasicBlock *BB); 00119 }; 00120 00121 /// Traverse the blocks in a loop using a depth-first search. 00122 class LoopBlocksTraversal { 00123 public: 00124 /// Graph traversal iterator. 00125 typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator; 00126 00127 private: 00128 LoopBlocksDFS &DFS; 00129 LoopInfo *LI; 00130 00131 public: 00132 LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) : 00133 DFS(Storage), LI(LInfo) {} 00134 00135 /// Postorder traversal over the graph. This only needs to be done once. 00136 /// po_iterator "automatically" calls back to visitPreorder and 00137 /// finishPostorder to record the DFS result. 00138 POTIterator begin() { 00139 assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing"); 00140 assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph"); 00141 return po_ext_begin(DFS.L->getHeader(), *this); 00142 } 00143 POTIterator end() { 00144 // po_ext_end interface requires a basic block, but ignores its value. 00145 return po_ext_end(DFS.L->getHeader(), *this); 00146 } 00147 00148 /// Called by po_iterator upon reaching a block via a CFG edge. If this block 00149 /// is contained in the loop and has not been visited, then mark it preorder 00150 /// visited and return true. 00151 /// 00152 /// TODO: If anyone is interested, we could record preorder numbers here. 00153 bool visitPreorder(BasicBlock *BB) { 00154 if (!DFS.L->contains(LI->getLoopFor(BB))) 00155 return false; 00156 00157 return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second; 00158 } 00159 00160 /// Called by po_iterator each time it advances, indicating a block's 00161 /// postorder. 00162 void finishPostorder(BasicBlock *BB) { 00163 assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder"); 00164 DFS.PostBlocks.push_back(BB); 00165 DFS.PostNumbers[BB] = DFS.PostBlocks.size(); 00166 } 00167 }; 00168 00169 inline bool po_iterator_storage<LoopBlocksTraversal, true>:: 00170 insertEdge(BasicBlock *From, BasicBlock *To) { 00171 return LBT.visitPreorder(To); 00172 } 00173 00174 inline void po_iterator_storage<LoopBlocksTraversal, true>:: 00175 finishPostorder(BasicBlock *BB) { 00176 LBT.finishPostorder(BB); 00177 } 00178 00179 } // End namespace llvm 00180 00181 #endif