GenericCycleInfo.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- GenericCycleInfo.h - Info for Cycles in any IR ------*- 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. ///
  14. /// \file
  15. /// \brief Find all cycles in a control-flow graph, including irreducible loops.
  16. ///
  17. /// See docs/CycleTerminology.rst for a formal definition of cycles.
  18. ///
  19. /// Briefly:
  20. /// - A cycle is a generalization of a loop which can represent
  21. /// irreducible control flow.
  22. /// - Cycles identified in a program are implementation defined,
  23. /// depending on the DFS traversal chosen.
  24. /// - Cycles are well-nested, and form a forest with a parent-child
  25. /// relationship.
  26. /// - In any choice of DFS, every natural loop L is represented by a
  27. /// unique cycle C which is a superset of L.
  28. /// - In the absence of irreducible control flow, the cycles are
  29. /// exactly the natural loops in the program.
  30. ///
  31. //===----------------------------------------------------------------------===//
  32. #ifndef LLVM_ADT_GENERICCYCLEINFO_H
  33. #define LLVM_ADT_GENERICCYCLEINFO_H
  34. #include "llvm/ADT/ArrayRef.h"
  35. #include "llvm/ADT/DenseMap.h"
  36. #include "llvm/ADT/GenericSSAContext.h"
  37. #include "llvm/ADT/GraphTraits.h"
  38. #include "llvm/ADT/SmallVector.h"
  39. #include "llvm/ADT/iterator.h"
  40. #include "llvm/Support/Debug.h"
  41. #include "llvm/Support/Printable.h"
  42. #include "llvm/Support/raw_ostream.h"
  43. #include <vector>
  44. namespace llvm {
  45. template <typename ContextT> class GenericCycleInfo;
  46. template <typename ContextT> class GenericCycleInfoCompute;
  47. /// A possibly irreducible generalization of a \ref Loop.
  48. template <typename ContextT> class GenericCycle {
  49. public:
  50. using BlockT = typename ContextT::BlockT;
  51. using FunctionT = typename ContextT::FunctionT;
  52. template <typename> friend class GenericCycleInfo;
  53. template <typename> friend class GenericCycleInfoCompute;
  54. private:
  55. /// The parent cycle. Is null for the root "cycle". Top-level cycles point
  56. /// at the root.
  57. GenericCycle *ParentCycle = nullptr;
  58. /// The entry block(s) of the cycle. The header is the only entry if
  59. /// this is a loop. Is empty for the root "cycle", to avoid
  60. /// unnecessary memory use.
  61. SmallVector<BlockT *, 1> Entries;
  62. /// Child cycles, if any.
  63. std::vector<std::unique_ptr<GenericCycle>> Children;
  64. /// Basic blocks that are contained in the cycle, including entry blocks,
  65. /// and including blocks that are part of a child cycle.
  66. std::vector<BlockT *> Blocks;
  67. /// Depth of the cycle in the tree. The root "cycle" is at depth 0.
  68. ///
  69. /// \note Depths are not necessarily contiguous. However, child loops always
  70. /// have strictly greater depth than their parents, and sibling loops
  71. /// always have the same depth.
  72. unsigned Depth = 0;
  73. void clear() {
  74. Entries.clear();
  75. Children.clear();
  76. Blocks.clear();
  77. Depth = 0;
  78. ParentCycle = nullptr;
  79. }
  80. void appendEntry(BlockT *Block) { Entries.push_back(Block); }
  81. void appendBlock(BlockT *Block) { Blocks.push_back(Block); }
  82. GenericCycle(const GenericCycle &) = delete;
  83. GenericCycle &operator=(const GenericCycle &) = delete;
  84. GenericCycle(GenericCycle &&Rhs) = delete;
  85. GenericCycle &operator=(GenericCycle &&Rhs) = delete;
  86. public:
  87. GenericCycle() = default;
  88. /// \brief Whether the cycle is a natural loop.
  89. bool isReducible() const { return Entries.size() == 1; }
  90. BlockT *getHeader() const { return Entries[0]; }
  91. const SmallVectorImpl<BlockT *> & getEntries() const {
  92. return Entries;
  93. }
  94. /// \brief Return whether \p Block is an entry block of the cycle.
  95. bool isEntry(const BlockT *Block) const {
  96. return is_contained(Entries, Block);
  97. }
  98. /// \brief Return whether \p Block is contained in the cycle.
  99. bool contains(const BlockT *Block) const {
  100. return is_contained(Blocks, Block);
  101. }
  102. /// \brief Returns true iff this cycle contains \p C.
  103. ///
  104. /// Note: Non-strict containment check, i.e. returns true if C is the
  105. /// same cycle.
  106. bool contains(const GenericCycle *C) const;
  107. const GenericCycle *getParentCycle() const { return ParentCycle; }
  108. GenericCycle *getParentCycle() { return ParentCycle; }
  109. unsigned getDepth() const { return Depth; }
  110. /// Return all of the successor blocks of this cycle.
  111. ///
  112. /// These are the blocks _outside of the current cycle_ which are
  113. /// branched to.
  114. void getExitBlocks(SmallVectorImpl<BlockT *> &TmpStorage) const;
  115. /// Return the preheader block for this cycle. Pre-header is well-defined for
  116. /// reducible cycle in docs/LoopTerminology.rst as: the only one entering
  117. /// block and its only edge is to the entry block. Return null for irreducible
  118. /// cycles.
  119. BlockT *getCyclePreheader() const;
  120. /// If the cycle has exactly one entry with exactly one predecessor, return
  121. /// it, otherwise return nullptr.
  122. BlockT *getCyclePredecessor() const;
  123. /// Iteration over child cycles.
  124. //@{
  125. using const_child_iterator_base =
  126. typename std::vector<std::unique_ptr<GenericCycle>>::const_iterator;
  127. struct const_child_iterator
  128. : iterator_adaptor_base<const_child_iterator, const_child_iterator_base> {
  129. using Base =
  130. iterator_adaptor_base<const_child_iterator, const_child_iterator_base>;
  131. const_child_iterator() = default;
  132. explicit const_child_iterator(const_child_iterator_base I) : Base(I) {}
  133. const const_child_iterator_base &wrapped() { return Base::wrapped(); }
  134. GenericCycle *operator*() const { return Base::I->get(); }
  135. };
  136. const_child_iterator child_begin() const {
  137. return const_child_iterator{Children.begin()};
  138. }
  139. const_child_iterator child_end() const {
  140. return const_child_iterator{Children.end()};
  141. }
  142. size_t getNumChildren() const { return Children.size(); }
  143. iterator_range<const_child_iterator> children() const {
  144. return llvm::make_range(const_child_iterator{Children.begin()},
  145. const_child_iterator{Children.end()});
  146. }
  147. //@}
  148. /// Iteration over blocks in the cycle (including entry blocks).
  149. //@{
  150. using const_block_iterator = typename std::vector<BlockT *>::const_iterator;
  151. const_block_iterator block_begin() const {
  152. return const_block_iterator{Blocks.begin()};
  153. }
  154. const_block_iterator block_end() const {
  155. return const_block_iterator{Blocks.end()};
  156. }
  157. size_t getNumBlocks() const { return Blocks.size(); }
  158. iterator_range<const_block_iterator> blocks() const {
  159. return llvm::make_range(block_begin(), block_end());
  160. }
  161. //@}
  162. /// Iteration over entry blocks.
  163. //@{
  164. using const_entry_iterator =
  165. typename SmallVectorImpl<BlockT *>::const_iterator;
  166. size_t getNumEntries() const { return Entries.size(); }
  167. iterator_range<const_entry_iterator> entries() const {
  168. return llvm::make_range(Entries.begin(), Entries.end());
  169. }
  170. //@}
  171. Printable printEntries(const ContextT &Ctx) const {
  172. return Printable([this, &Ctx](raw_ostream &Out) {
  173. bool First = true;
  174. for (auto *Entry : Entries) {
  175. if (!First)
  176. Out << ' ';
  177. First = false;
  178. Out << Ctx.print(Entry);
  179. }
  180. });
  181. }
  182. Printable print(const ContextT &Ctx) const {
  183. return Printable([this, &Ctx](raw_ostream &Out) {
  184. Out << "depth=" << Depth << ": entries(" << printEntries(Ctx) << ')';
  185. for (auto *Block : Blocks) {
  186. if (isEntry(Block))
  187. continue;
  188. Out << ' ' << Ctx.print(Block);
  189. }
  190. });
  191. }
  192. };
  193. /// \brief Cycle information for a function.
  194. template <typename ContextT> class GenericCycleInfo {
  195. public:
  196. using BlockT = typename ContextT::BlockT;
  197. using CycleT = GenericCycle<ContextT>;
  198. using FunctionT = typename ContextT::FunctionT;
  199. template <typename> friend class GenericCycle;
  200. template <typename> friend class GenericCycleInfoCompute;
  201. private:
  202. ContextT Context;
  203. /// Map basic blocks to their inner-most containing cycle.
  204. DenseMap<BlockT *, CycleT *> BlockMap;
  205. /// Map basic blocks to their top level containing cycle.
  206. DenseMap<BlockT *, CycleT *> BlockMapTopLevel;
  207. /// Top-level cycles discovered by any DFS.
  208. ///
  209. /// Note: The implementation treats the nullptr as the parent of
  210. /// every top-level cycle. See \ref contains for an example.
  211. std::vector<std::unique_ptr<CycleT>> TopLevelCycles;
  212. /// Move \p Child to \p NewParent by manipulating Children vectors.
  213. ///
  214. /// Note: This is an incomplete operation that does not update the depth of
  215. /// the subtree.
  216. void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);
  217. public:
  218. GenericCycleInfo() = default;
  219. GenericCycleInfo(GenericCycleInfo &&) = default;
  220. GenericCycleInfo &operator=(GenericCycleInfo &&) = default;
  221. void clear();
  222. void compute(FunctionT &F);
  223. FunctionT *getFunction() const { return Context.getFunction(); }
  224. const ContextT &getSSAContext() const { return Context; }
  225. CycleT *getCycle(const BlockT *Block) const;
  226. unsigned getCycleDepth(const BlockT *Block) const;
  227. CycleT *getTopLevelParentCycle(BlockT *Block);
  228. /// Methods for debug and self-test.
  229. //@{
  230. #ifndef NDEBUG
  231. bool validateTree() const;
  232. #endif
  233. void print(raw_ostream &Out) const;
  234. void dump() const { print(dbgs()); }
  235. //@}
  236. /// Iteration over top-level cycles.
  237. //@{
  238. using const_toplevel_iterator_base =
  239. typename std::vector<std::unique_ptr<CycleT>>::const_iterator;
  240. struct const_toplevel_iterator
  241. : iterator_adaptor_base<const_toplevel_iterator,
  242. const_toplevel_iterator_base> {
  243. using Base = iterator_adaptor_base<const_toplevel_iterator,
  244. const_toplevel_iterator_base>;
  245. const_toplevel_iterator() = default;
  246. explicit const_toplevel_iterator(const_toplevel_iterator_base I)
  247. : Base(I) {}
  248. const const_toplevel_iterator_base &wrapped() { return Base::wrapped(); }
  249. CycleT *operator*() const { return Base::I->get(); }
  250. };
  251. const_toplevel_iterator toplevel_begin() const {
  252. return const_toplevel_iterator{TopLevelCycles.begin()};
  253. }
  254. const_toplevel_iterator toplevel_end() const {
  255. return const_toplevel_iterator{TopLevelCycles.end()};
  256. }
  257. iterator_range<const_toplevel_iterator> toplevel_cycles() const {
  258. return llvm::make_range(const_toplevel_iterator{TopLevelCycles.begin()},
  259. const_toplevel_iterator{TopLevelCycles.end()});
  260. }
  261. //@}
  262. };
  263. /// \brief GraphTraits for iterating over a sub-tree of the CycleT tree.
  264. template <typename CycleRefT, typename ChildIteratorT> struct CycleGraphTraits {
  265. using NodeRef = CycleRefT;
  266. using nodes_iterator = ChildIteratorT;
  267. using ChildIteratorType = nodes_iterator;
  268. static NodeRef getEntryNode(NodeRef Graph) { return Graph; }
  269. static ChildIteratorType child_begin(NodeRef Ref) {
  270. return Ref->child_begin();
  271. }
  272. static ChildIteratorType child_end(NodeRef Ref) { return Ref->child_end(); }
  273. // Not implemented:
  274. // static nodes_iterator nodes_begin(GraphType *G)
  275. // static nodes_iterator nodes_end (GraphType *G)
  276. // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
  277. // typedef EdgeRef - Type of Edge token in the graph, which should
  278. // be cheap to copy.
  279. // typedef ChildEdgeIteratorType - Type used to iterate over children edges in
  280. // graph, dereference to a EdgeRef.
  281. // static ChildEdgeIteratorType child_edge_begin(NodeRef)
  282. // static ChildEdgeIteratorType child_edge_end(NodeRef)
  283. // Return iterators that point to the beginning and ending of the
  284. // edge list for the given callgraph node.
  285. //
  286. // static NodeRef edge_dest(EdgeRef)
  287. // Return the destination node of an edge.
  288. // static unsigned size (GraphType *G)
  289. // Return total number of nodes in the graph
  290. };
  291. template <typename BlockT>
  292. struct GraphTraits<const GenericCycle<BlockT> *>
  293. : CycleGraphTraits<const GenericCycle<BlockT> *,
  294. typename GenericCycle<BlockT>::const_child_iterator> {};
  295. template <typename BlockT>
  296. struct GraphTraits<GenericCycle<BlockT> *>
  297. : CycleGraphTraits<GenericCycle<BlockT> *,
  298. typename GenericCycle<BlockT>::const_child_iterator> {};
  299. } // namespace llvm
  300. #endif // LLVM_ADT_GENERICCYCLEINFO_H
  301. #ifdef __GNUC__
  302. #pragma GCC diagnostic pop
  303. #endif