1 //===- GenericCycleInfo.h - Info for Cycles in any IR ------*- C++ -*------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// \brief Find all cycles in a control-flow graph, including irreducible loops. 11 /// 12 /// See docs/CycleTerminology.rst for a formal definition of cycles. 13 /// 14 /// Briefly: 15 /// - A cycle is a generalization of a loop which can represent 16 /// irreducible control flow. 17 /// - Cycles identified in a program are implementation defined, 18 /// depending on the DFS traversal chosen. 19 /// - Cycles are well-nested, and form a forest with a parent-child 20 /// relationship. 21 /// - In any choice of DFS, every natural loop L is represented by a 22 /// unique cycle C which is a superset of L. 23 /// - In the absence of irreducible control flow, the cycles are 24 /// exactly the natural loops in the program. 25 /// 26 //===----------------------------------------------------------------------===// 27 28 #ifndef LLVM_ADT_GENERICCYCLEINFO_H 29 #define LLVM_ADT_GENERICCYCLEINFO_H 30 31 #include "llvm/ADT/DenseSet.h" 32 #include "llvm/ADT/GenericSSAContext.h" 33 #include "llvm/ADT/GraphTraits.h" 34 #include "llvm/ADT/SetVector.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/raw_ostream.h" 37 38 namespace llvm { 39 40 template <typename ContextT> class GenericCycleInfo; 41 template <typename ContextT> class GenericCycleInfoCompute; 42 43 /// A possibly irreducible generalization of a \ref Loop. 44 template <typename ContextT> class GenericCycle { 45 public: 46 using BlockT = typename ContextT::BlockT; 47 using FunctionT = typename ContextT::FunctionT; 48 template <typename> friend class GenericCycleInfo; 49 template <typename> friend class GenericCycleInfoCompute; 50 51 private: 52 /// The parent cycle. Is null for the root "cycle". Top-level cycles point 53 /// at the root. 54 GenericCycle *ParentCycle = nullptr; 55 56 /// The entry block(s) of the cycle. The header is the only entry if 57 /// this is a loop. Is empty for the root "cycle", to avoid 58 /// unnecessary memory use. 59 SmallVector<BlockT *, 1> Entries; 60 61 /// Child cycles, if any. 62 std::vector<std::unique_ptr<GenericCycle>> Children; 63 64 /// Basic blocks that are contained in the cycle, including entry blocks, 65 /// and including blocks that are part of a child cycle. 66 using BlockSetVectorT = SetVector<BlockT *, SmallVector<BlockT *, 8>, 67 DenseSet<const BlockT *>, 8>; 68 BlockSetVectorT Blocks; 69 70 /// Depth of the cycle in the tree. The root "cycle" is at depth 0. 71 /// 72 /// \note Depths are not necessarily contiguous. However, child loops always 73 /// have strictly greater depth than their parents, and sibling loops 74 /// always have the same depth. 75 unsigned Depth = 0; 76 77 /// Cache for the results of GetExitBlocks 78 mutable SmallVector<BlockT *, 4> ExitBlocksCache; 79 80 void clear() { 81 Entries.clear(); 82 Children.clear(); 83 Blocks.clear(); 84 Depth = 0; 85 ParentCycle = nullptr; 86 clearCache(); 87 } 88 89 void appendEntry(BlockT *Block) { 90 Entries.push_back(Block); 91 clearCache(); 92 } 93 94 void appendBlock(BlockT *Block) { 95 Blocks.insert(Block); 96 clearCache(); 97 } 98 99 GenericCycle(const GenericCycle &) = delete; 100 GenericCycle &operator=(const GenericCycle &) = delete; 101 GenericCycle(GenericCycle &&Rhs) = delete; 102 GenericCycle &operator=(GenericCycle &&Rhs) = delete; 103 104 public: 105 GenericCycle() = default; 106 107 /// \brief Whether the cycle is a natural loop. 108 bool isReducible() const { return Entries.size() == 1; } 109 110 BlockT *getHeader() const { return Entries[0]; } 111 112 const SmallVectorImpl<BlockT *> & getEntries() const { 113 return Entries; 114 } 115 116 /// Clear the cache of the cycle. 117 /// This should be run in all non-const function in GenericCycle 118 /// and GenericCycleInfo. 119 void clearCache() const { ExitBlocksCache.clear(); } 120 121 /// \brief Return whether \p Block is an entry block of the cycle. 122 bool isEntry(const BlockT *Block) const { 123 return is_contained(Entries, Block); 124 } 125 126 /// \brief Replace all entries with \p Block as single entry. 127 void setSingleEntry(BlockT *Block) { 128 assert(contains(Block)); 129 Entries.clear(); 130 Entries.push_back(Block); 131 clearCache(); 132 } 133 134 /// \brief Return whether \p Block is contained in the cycle. 135 bool contains(const BlockT *Block) const { return Blocks.contains(Block); } 136 137 /// \brief Returns true iff this cycle contains \p C. 138 /// 139 /// Note: Non-strict containment check, i.e. returns true if C is the 140 /// same cycle. 141 bool contains(const GenericCycle *C) const; 142 143 const GenericCycle *getParentCycle() const { return ParentCycle; } 144 GenericCycle *getParentCycle() { return ParentCycle; } 145 unsigned getDepth() const { return Depth; } 146 147 /// Return all of the successor blocks of this cycle. 148 /// 149 /// These are the blocks _outside of the current cycle_ which are 150 /// branched to. 151 void getExitBlocks(SmallVectorImpl<BlockT *> &TmpStorage) const; 152 153 /// Return all blocks of this cycle that have successor outside of this cycle. 154 /// These blocks have cycle exit branch. 155 void getExitingBlocks(SmallVectorImpl<BlockT *> &TmpStorage) const; 156 157 /// Return the preheader block for this cycle. Pre-header is well-defined for 158 /// reducible cycle in docs/LoopTerminology.rst as: the only one entering 159 /// block and its only edge is to the entry block. Return null for irreducible 160 /// cycles. 161 BlockT *getCyclePreheader() const; 162 163 /// If the cycle has exactly one entry with exactly one predecessor, return 164 /// it, otherwise return nullptr. 165 BlockT *getCyclePredecessor() const; 166 167 void verifyCycle() const; 168 void verifyCycleNest() const; 169 170 /// Iteration over child cycles. 171 //@{ 172 using const_child_iterator_base = 173 typename std::vector<std::unique_ptr<GenericCycle>>::const_iterator; 174 struct const_child_iterator 175 : iterator_adaptor_base<const_child_iterator, const_child_iterator_base> { 176 using Base = 177 iterator_adaptor_base<const_child_iterator, const_child_iterator_base>; 178 179 const_child_iterator() = default; 180 explicit const_child_iterator(const_child_iterator_base I) : Base(I) {} 181 182 const const_child_iterator_base &wrapped() { return Base::wrapped(); } 183 GenericCycle *operator*() const { return Base::I->get(); } 184 }; 185 186 const_child_iterator child_begin() const { 187 return const_child_iterator{Children.begin()}; 188 } 189 const_child_iterator child_end() const { 190 return const_child_iterator{Children.end()}; 191 } 192 size_t getNumChildren() const { return Children.size(); } 193 iterator_range<const_child_iterator> children() const { 194 return llvm::make_range(const_child_iterator{Children.begin()}, 195 const_child_iterator{Children.end()}); 196 } 197 //@} 198 199 /// Iteration over blocks in the cycle (including entry blocks). 200 //@{ 201 using const_block_iterator = typename BlockSetVectorT::const_iterator; 202 203 const_block_iterator block_begin() const { 204 return const_block_iterator{Blocks.begin()}; 205 } 206 const_block_iterator block_end() const { 207 return const_block_iterator{Blocks.end()}; 208 } 209 size_t getNumBlocks() const { return Blocks.size(); } 210 iterator_range<const_block_iterator> blocks() const { 211 return llvm::make_range(block_begin(), block_end()); 212 } 213 //@} 214 215 /// Iteration over entry blocks. 216 //@{ 217 using const_entry_iterator = 218 typename SmallVectorImpl<BlockT *>::const_iterator; 219 const_entry_iterator entry_begin() const { return Entries.begin(); } 220 const_entry_iterator entry_end() const { return Entries.end(); } 221 size_t getNumEntries() const { return Entries.size(); } 222 iterator_range<const_entry_iterator> entries() const { 223 return llvm::make_range(entry_begin(), entry_end()); 224 } 225 using const_reverse_entry_iterator = 226 typename SmallVectorImpl<BlockT *>::const_reverse_iterator; 227 const_reverse_entry_iterator entry_rbegin() const { return Entries.rbegin(); } 228 const_reverse_entry_iterator entry_rend() const { return Entries.rend(); } 229 //@} 230 231 Printable printEntries(const ContextT &Ctx) const { 232 return Printable([this, &Ctx](raw_ostream &Out) { 233 bool First = true; 234 for (auto *Entry : Entries) { 235 if (!First) 236 Out << ' '; 237 First = false; 238 Out << Ctx.print(Entry); 239 } 240 }); 241 } 242 243 Printable print(const ContextT &Ctx) const { 244 return Printable([this, &Ctx](raw_ostream &Out) { 245 Out << "depth=" << Depth << ": entries(" << printEntries(Ctx) << ')'; 246 247 for (auto *Block : Blocks) { 248 if (isEntry(Block)) 249 continue; 250 251 Out << ' ' << Ctx.print(Block); 252 } 253 }); 254 } 255 }; 256 257 /// \brief Cycle information for a function. 258 template <typename ContextT> class GenericCycleInfo { 259 public: 260 using BlockT = typename ContextT::BlockT; 261 using CycleT = GenericCycle<ContextT>; 262 using FunctionT = typename ContextT::FunctionT; 263 template <typename> friend class GenericCycle; 264 template <typename> friend class GenericCycleInfoCompute; 265 266 private: 267 ContextT Context; 268 269 /// Map basic blocks to their inner-most containing cycle. 270 DenseMap<BlockT *, CycleT *> BlockMap; 271 272 /// Map basic blocks to their top level containing cycle. 273 DenseMap<BlockT *, CycleT *> BlockMapTopLevel; 274 275 /// Top-level cycles discovered by any DFS. 276 /// 277 /// Note: The implementation treats the nullptr as the parent of 278 /// every top-level cycle. See \ref contains for an example. 279 std::vector<std::unique_ptr<CycleT>> TopLevelCycles; 280 281 /// Move \p Child to \p NewParent by manipulating Children vectors. 282 /// 283 /// Note: This is an incomplete operation that does not update the depth of 284 /// the subtree. 285 void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child); 286 287 public: 288 GenericCycleInfo() = default; 289 GenericCycleInfo(GenericCycleInfo &&) = default; 290 GenericCycleInfo &operator=(GenericCycleInfo &&) = default; 291 292 void clear(); 293 void compute(FunctionT &F); 294 void splitCriticalEdge(BlockT *Pred, BlockT *Succ, BlockT *New); 295 296 const FunctionT *getFunction() const { return Context.getFunction(); } 297 const ContextT &getSSAContext() const { return Context; } 298 299 CycleT *getCycle(const BlockT *Block) const; 300 CycleT *getSmallestCommonCycle(CycleT *A, CycleT *B) const; 301 unsigned getCycleDepth(const BlockT *Block) const; 302 CycleT *getTopLevelParentCycle(BlockT *Block); 303 304 /// Assumes that \p Cycle is the innermost cycle containing \p Block. 305 /// \p Block will be appended to \p Cycle and all of its parent cycles. 306 /// \p Block will be added to BlockMap with \p Cycle and 307 /// BlockMapTopLevel with \p Cycle's top level parent cycle. 308 void addBlockToCycle(BlockT *Block, CycleT *Cycle); 309 310 /// Methods for debug and self-test. 311 //@{ 312 void verifyCycleNest(bool VerifyFull = false) const; 313 void verify() const; 314 void print(raw_ostream &Out) const; 315 void dump() const { print(dbgs()); } 316 Printable print(const CycleT *Cycle) { return Cycle->print(Context); } 317 //@} 318 319 /// Iteration over top-level cycles. 320 //@{ 321 using const_toplevel_iterator_base = 322 typename std::vector<std::unique_ptr<CycleT>>::const_iterator; 323 struct const_toplevel_iterator 324 : iterator_adaptor_base<const_toplevel_iterator, 325 const_toplevel_iterator_base> { 326 using Base = iterator_adaptor_base<const_toplevel_iterator, 327 const_toplevel_iterator_base>; 328 329 const_toplevel_iterator() = default; 330 explicit const_toplevel_iterator(const_toplevel_iterator_base I) 331 : Base(I) {} 332 333 const const_toplevel_iterator_base &wrapped() { return Base::wrapped(); } 334 CycleT *operator*() const { return Base::I->get(); } 335 }; 336 337 const_toplevel_iterator toplevel_begin() const { 338 return const_toplevel_iterator{TopLevelCycles.begin()}; 339 } 340 const_toplevel_iterator toplevel_end() const { 341 return const_toplevel_iterator{TopLevelCycles.end()}; 342 } 343 344 iterator_range<const_toplevel_iterator> toplevel_cycles() const { 345 return llvm::make_range(const_toplevel_iterator{TopLevelCycles.begin()}, 346 const_toplevel_iterator{TopLevelCycles.end()}); 347 } 348 //@} 349 }; 350 351 /// \brief GraphTraits for iterating over a sub-tree of the CycleT tree. 352 template <typename CycleRefT, typename ChildIteratorT> struct CycleGraphTraits { 353 using NodeRef = CycleRefT; 354 355 using nodes_iterator = ChildIteratorT; 356 using ChildIteratorType = nodes_iterator; 357 358 static NodeRef getEntryNode(NodeRef Graph) { return Graph; } 359 360 static ChildIteratorType child_begin(NodeRef Ref) { 361 return Ref->child_begin(); 362 } 363 static ChildIteratorType child_end(NodeRef Ref) { return Ref->child_end(); } 364 365 // Not implemented: 366 // static nodes_iterator nodes_begin(GraphType *G) 367 // static nodes_iterator nodes_end (GraphType *G) 368 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph 369 370 // typedef EdgeRef - Type of Edge token in the graph, which should 371 // be cheap to copy. 372 // typedef ChildEdgeIteratorType - Type used to iterate over children edges in 373 // graph, dereference to a EdgeRef. 374 375 // static ChildEdgeIteratorType child_edge_begin(NodeRef) 376 // static ChildEdgeIteratorType child_edge_end(NodeRef) 377 // Return iterators that point to the beginning and ending of the 378 // edge list for the given callgraph node. 379 // 380 // static NodeRef edge_dest(EdgeRef) 381 // Return the destination node of an edge. 382 // static unsigned size (GraphType *G) 383 // Return total number of nodes in the graph 384 }; 385 386 template <typename BlockT> 387 struct GraphTraits<const GenericCycle<BlockT> *> 388 : CycleGraphTraits<const GenericCycle<BlockT> *, 389 typename GenericCycle<BlockT>::const_child_iterator> {}; 390 template <typename BlockT> 391 struct GraphTraits<GenericCycle<BlockT> *> 392 : CycleGraphTraits<GenericCycle<BlockT> *, 393 typename GenericCycle<BlockT>::const_child_iterator> {}; 394 395 } // namespace llvm 396 397 #endif // LLVM_ADT_GENERICCYCLEINFO_H 398