Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
6.0 KiB

  1. //===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. // This file defines iterators to visit the basic blocks within a loop.
  10. //
  11. // These iterators currently visit blocks within subloops as well.
  12. // Unfortunately we have no efficient way of summarizing loop exits which would
  13. // allow skipping subloops during traversal.
  14. //
  15. // If you want to visit all blocks in a loop and don't need an ordered traveral,
  16. // use Loop::block_begin() instead.
  17. //
  18. // This is intentionally designed to work with ill-formed loops in which the
  19. // backedge has been deleted. The only prerequisite is that all blocks
  20. // contained within the loop according to the most recent LoopInfo analysis are
  21. // reachable from the loop header.
  22. //===----------------------------------------------------------------------===//
  23. #ifndef LLVM_ANALYSIS_LOOPITERATOR_H
  24. #define LLVM_ANALYSIS_LOOPITERATOR_H
  25. #include "llvm/ADT/PostOrderIterator.h"
  26. #include "llvm/Analysis/LoopInfo.h"
  27. namespace llvm {
  28. class LoopBlocksTraversal;
  29. /// Store the result of a depth first search within basic blocks contained by a
  30. /// single loop.
  31. ///
  32. /// TODO: This could be generalized for any CFG region, or the entire CFG.
  33. class LoopBlocksDFS {
  34. public:
  35. /// Postorder list iterators.
  36. typedef std::vector<BasicBlock*>::const_iterator POIterator;
  37. typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
  38. friend class LoopBlocksTraversal;
  39. private:
  40. Loop *L;
  41. /// Map each block to its postorder number. A block is only mapped after it is
  42. /// preorder visited by DFS. It's postorder number is initially zero and set
  43. /// to nonzero after it is finished by postorder traversal.
  44. DenseMap<BasicBlock*, unsigned> PostNumbers;
  45. std::vector<BasicBlock*> PostBlocks;
  46. public:
  47. LoopBlocksDFS(Loop *Container) :
  48. L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
  49. PostBlocks.reserve(Container->getNumBlocks());
  50. }
  51. Loop *getLoop() const { return L; }
  52. /// Traverse the loop blocks and store the DFS result.
  53. void perform(LoopInfo *LI);
  54. /// Return true if postorder numbers are assigned to all loop blocks.
  55. bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
  56. /// Iterate over the cached postorder blocks.
  57. POIterator beginPostorder() const {
  58. assert(isComplete() && "bad loop DFS");
  59. return PostBlocks.begin();
  60. }
  61. POIterator endPostorder() const { return PostBlocks.end(); }
  62. /// Reverse iterate over the cached postorder blocks.
  63. RPOIterator beginRPO() const {
  64. assert(isComplete() && "bad loop DFS");
  65. return PostBlocks.rbegin();
  66. }
  67. RPOIterator endRPO() const { return PostBlocks.rend(); }
  68. /// Return true if this block has been preorder visited.
  69. bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
  70. /// Return true if this block has a postorder number.
  71. bool hasPostorder(BasicBlock *BB) const {
  72. DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
  73. return I != PostNumbers.end() && I->second;
  74. }
  75. /// Get a block's postorder number.
  76. unsigned getPostorder(BasicBlock *BB) const {
  77. DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
  78. assert(I != PostNumbers.end() && "block not visited by DFS");
  79. assert(I->second && "block not finished by DFS");
  80. return I->second;
  81. }
  82. /// Get a block's reverse postorder number.
  83. unsigned getRPO(BasicBlock *BB) const {
  84. return 1 + PostBlocks.size() - getPostorder(BB);
  85. }
  86. void clear() {
  87. PostNumbers.clear();
  88. PostBlocks.clear();
  89. }
  90. };
  91. /// Specialize po_iterator_storage to record postorder numbers.
  92. template<> class po_iterator_storage<LoopBlocksTraversal, true> {
  93. LoopBlocksTraversal &LBT;
  94. public:
  95. po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {}
  96. // These functions are defined below.
  97. bool insertEdge(BasicBlock *From, BasicBlock *To);
  98. void finishPostorder(BasicBlock *BB);
  99. };
  100. /// Traverse the blocks in a loop using a depth-first search.
  101. class LoopBlocksTraversal {
  102. public:
  103. /// Graph traversal iterator.
  104. typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
  105. private:
  106. LoopBlocksDFS &DFS;
  107. LoopInfo *LI;
  108. public:
  109. LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) :
  110. DFS(Storage), LI(LInfo) {}
  111. /// Postorder traversal over the graph. This only needs to be done once.
  112. /// po_iterator "automatically" calls back to visitPreorder and
  113. /// finishPostorder to record the DFS result.
  114. POTIterator begin() {
  115. assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
  116. assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
  117. return po_ext_begin(DFS.L->getHeader(), *this);
  118. }
  119. POTIterator end() {
  120. // po_ext_end interface requires a basic block, but ignores its value.
  121. return po_ext_end(DFS.L->getHeader(), *this);
  122. }
  123. /// Called by po_iterator upon reaching a block via a CFG edge. If this block
  124. /// is contained in the loop and has not been visited, then mark it preorder
  125. /// visited and return true.
  126. ///
  127. /// TODO: If anyone is interested, we could record preorder numbers here.
  128. bool visitPreorder(BasicBlock *BB) {
  129. if (!DFS.L->contains(LI->getLoopFor(BB)))
  130. return false;
  131. return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
  132. }
  133. /// Called by po_iterator each time it advances, indicating a block's
  134. /// postorder.
  135. void finishPostorder(BasicBlock *BB) {
  136. assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
  137. DFS.PostBlocks.push_back(BB);
  138. DFS.PostNumbers[BB] = DFS.PostBlocks.size();
  139. }
  140. };
  141. inline bool po_iterator_storage<LoopBlocksTraversal, true>::
  142. insertEdge(BasicBlock *From, BasicBlock *To) {
  143. return LBT.visitPreorder(To);
  144. }
  145. inline void po_iterator_storage<LoopBlocksTraversal, true>::
  146. finishPostorder(BasicBlock *BB) {
  147. LBT.finishPostorder(BB);
  148. }
  149. } // End namespace llvm
  150. #endif