LoopIterator.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. // This file defines iterators to visit the basic blocks within a loop.
  14. //
  15. // These iterators currently visit blocks within subloops as well.
  16. // Unfortunately we have no efficient way of summarizing loop exits which would
  17. // allow skipping subloops during traversal.
  18. //
  19. // If you want to visit all blocks in a loop and don't need an ordered traveral,
  20. // use Loop::block_begin() instead.
  21. //
  22. // This is intentionally designed to work with ill-formed loops in which the
  23. // backedge has been deleted. The only prerequisite is that all blocks
  24. // contained within the loop according to the most recent LoopInfo analysis are
  25. // reachable from the loop header.
  26. //===----------------------------------------------------------------------===//
  27. #ifndef LLVM_ANALYSIS_LOOPITERATOR_H
  28. #define LLVM_ANALYSIS_LOOPITERATOR_H
  29. #include "llvm/ADT/PostOrderIterator.h"
  30. #include "llvm/Analysis/LoopInfo.h"
  31. namespace llvm {
  32. class LoopBlocksTraversal;
  33. // A traits type that is intended to be used in graph algorithms. The graph
  34. // traits starts at the loop header, and traverses the BasicBlocks that are in
  35. // the loop body, but not the loop header. Since the loop header is skipped,
  36. // the back edges are excluded.
  37. //
  38. // TODO: Explore the possibility to implement LoopBlocksTraversal in terms of
  39. // LoopBodyTraits, so that insertEdge doesn't have to be specialized.
  40. struct LoopBodyTraits {
  41. using NodeRef = std::pair<const Loop *, BasicBlock *>;
  42. // This wraps a const Loop * into the iterator, so we know which edges to
  43. // filter out.
  44. class WrappedSuccIterator
  45. : public iterator_adaptor_base<
  46. WrappedSuccIterator, succ_iterator,
  47. typename std::iterator_traits<succ_iterator>::iterator_category,
  48. NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> {
  49. using BaseT = iterator_adaptor_base<
  50. WrappedSuccIterator, succ_iterator,
  51. typename std::iterator_traits<succ_iterator>::iterator_category,
  52. NodeRef, std::ptrdiff_t, NodeRef *, NodeRef>;
  53. const Loop *L;
  54. public:
  55. WrappedSuccIterator(succ_iterator Begin, const Loop *L)
  56. : BaseT(Begin), L(L) {}
  57. NodeRef operator*() const { return {L, *I}; }
  58. };
  59. struct LoopBodyFilter {
  60. bool operator()(NodeRef N) const {
  61. const Loop *L = N.first;
  62. return N.second != L->getHeader() && L->contains(N.second);
  63. }
  64. };
  65. using ChildIteratorType =
  66. filter_iterator<WrappedSuccIterator, LoopBodyFilter>;
  67. static NodeRef getEntryNode(const Loop &G) { return {&G, G.getHeader()}; }
  68. static ChildIteratorType child_begin(NodeRef Node) {
  69. return make_filter_range(make_range<WrappedSuccIterator>(
  70. {succ_begin(Node.second), Node.first},
  71. {succ_end(Node.second), Node.first}),
  72. LoopBodyFilter{})
  73. .begin();
  74. }
  75. static ChildIteratorType child_end(NodeRef Node) {
  76. return make_filter_range(make_range<WrappedSuccIterator>(
  77. {succ_begin(Node.second), Node.first},
  78. {succ_end(Node.second), Node.first}),
  79. LoopBodyFilter{})
  80. .end();
  81. }
  82. };
  83. /// Store the result of a depth first search within basic blocks contained by a
  84. /// single loop.
  85. ///
  86. /// TODO: This could be generalized for any CFG region, or the entire CFG.
  87. class LoopBlocksDFS {
  88. public:
  89. /// Postorder list iterators.
  90. typedef std::vector<BasicBlock*>::const_iterator POIterator;
  91. typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
  92. friend class LoopBlocksTraversal;
  93. private:
  94. Loop *L;
  95. /// Map each block to its postorder number. A block is only mapped after it is
  96. /// preorder visited by DFS. It's postorder number is initially zero and set
  97. /// to nonzero after it is finished by postorder traversal.
  98. DenseMap<BasicBlock*, unsigned> PostNumbers;
  99. std::vector<BasicBlock*> PostBlocks;
  100. public:
  101. LoopBlocksDFS(Loop *Container) :
  102. L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
  103. PostBlocks.reserve(Container->getNumBlocks());
  104. }
  105. Loop *getLoop() const { return L; }
  106. /// Traverse the loop blocks and store the DFS result.
  107. void perform(LoopInfo *LI);
  108. /// Return true if postorder numbers are assigned to all loop blocks.
  109. bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
  110. /// Iterate over the cached postorder blocks.
  111. POIterator beginPostorder() const {
  112. assert(isComplete() && "bad loop DFS");
  113. return PostBlocks.begin();
  114. }
  115. POIterator endPostorder() const { return PostBlocks.end(); }
  116. /// Reverse iterate over the cached postorder blocks.
  117. RPOIterator beginRPO() const {
  118. assert(isComplete() && "bad loop DFS");
  119. return PostBlocks.rbegin();
  120. }
  121. RPOIterator endRPO() const { return PostBlocks.rend(); }
  122. /// Return true if this block has been preorder visited.
  123. bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
  124. /// Return true if this block has a postorder number.
  125. bool hasPostorder(BasicBlock *BB) const {
  126. DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
  127. return I != PostNumbers.end() && I->second;
  128. }
  129. /// Get a block's postorder number.
  130. unsigned getPostorder(BasicBlock *BB) const {
  131. DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
  132. assert(I != PostNumbers.end() && "block not visited by DFS");
  133. assert(I->second && "block not finished by DFS");
  134. return I->second;
  135. }
  136. /// Get a block's reverse postorder number.
  137. unsigned getRPO(BasicBlock *BB) const {
  138. return 1 + PostBlocks.size() - getPostorder(BB);
  139. }
  140. void clear() {
  141. PostNumbers.clear();
  142. PostBlocks.clear();
  143. }
  144. };
  145. /// Wrapper class to LoopBlocksDFS that provides a standard begin()/end()
  146. /// interface for the DFS reverse post-order traversal of blocks in a loop body.
  147. class LoopBlocksRPO {
  148. private:
  149. LoopBlocksDFS DFS;
  150. public:
  151. LoopBlocksRPO(Loop *Container) : DFS(Container) {}
  152. /// Traverse the loop blocks and store the DFS result.
  153. void perform(LoopInfo *LI) {
  154. DFS.perform(LI);
  155. }
  156. /// Reverse iterate over the cached postorder blocks.
  157. LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); }
  158. LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); }
  159. };
  160. /// Specialize po_iterator_storage to record postorder numbers.
  161. template<> class po_iterator_storage<LoopBlocksTraversal, true> {
  162. LoopBlocksTraversal &LBT;
  163. public:
  164. po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {}
  165. // These functions are defined below.
  166. bool insertEdge(std::optional<BasicBlock *> From, BasicBlock *To);
  167. void finishPostorder(BasicBlock *BB);
  168. };
  169. /// Traverse the blocks in a loop using a depth-first search.
  170. class LoopBlocksTraversal {
  171. public:
  172. /// Graph traversal iterator.
  173. typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
  174. private:
  175. LoopBlocksDFS &DFS;
  176. LoopInfo *LI;
  177. public:
  178. LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) :
  179. DFS(Storage), LI(LInfo) {}
  180. /// Postorder traversal over the graph. This only needs to be done once.
  181. /// po_iterator "automatically" calls back to visitPreorder and
  182. /// finishPostorder to record the DFS result.
  183. POTIterator begin() {
  184. assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
  185. assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
  186. return po_ext_begin(DFS.L->getHeader(), *this);
  187. }
  188. POTIterator end() {
  189. // po_ext_end interface requires a basic block, but ignores its value.
  190. return po_ext_end(DFS.L->getHeader(), *this);
  191. }
  192. /// Called by po_iterator upon reaching a block via a CFG edge. If this block
  193. /// is contained in the loop and has not been visited, then mark it preorder
  194. /// visited and return true.
  195. ///
  196. /// TODO: If anyone is interested, we could record preorder numbers here.
  197. bool visitPreorder(BasicBlock *BB) {
  198. if (!DFS.L->contains(LI->getLoopFor(BB)))
  199. return false;
  200. return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
  201. }
  202. /// Called by po_iterator each time it advances, indicating a block's
  203. /// postorder.
  204. void finishPostorder(BasicBlock *BB) {
  205. assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
  206. DFS.PostBlocks.push_back(BB);
  207. DFS.PostNumbers[BB] = DFS.PostBlocks.size();
  208. }
  209. };
  210. inline bool po_iterator_storage<LoopBlocksTraversal, true>::insertEdge(
  211. std::optional<BasicBlock *> From, BasicBlock *To) {
  212. return LBT.visitPreorder(To);
  213. }
  214. inline void po_iterator_storage<LoopBlocksTraversal, true>::
  215. finishPostorder(BasicBlock *BB) {
  216. LBT.finishPostorder(BB);
  217. }
  218. } // End namespace llvm
  219. #endif
  220. #ifdef __GNUC__
  221. #pragma GCC diagnostic pop
  222. #endif