LLVM 24.0.0git
GenericCycleImpl.h
Go to the documentation of this file.
1//===- GenericCycleImpl.h -------------------------------------*- 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/// This template implementation resides in a separate file so that it
11/// does not get injected into every .cpp file that includes the
12/// generic header.
13///
14/// DO NOT INCLUDE THIS FILE WHEN MERELY USING CYCLEINFO.
15///
16/// This file should only be included by files that implement a
17/// specialization of the relevant templates. Currently these are:
18/// - llvm/lib/IR/CycleInfo.cpp
19/// - llvm/lib/CodeGen/MachineCycleAnalysis.cpp
20///
21//===----------------------------------------------------------------------===//
22
23#ifndef LLVM_ADT_GENERICCYCLEIMPL_H
24#define LLVM_ADT_GENERICCYCLEIMPL_H
25
26#include "llvm/ADT/DenseSet.h"
30#include <iterator>
31
32#define DEBUG_TYPE "generic-cycle-impl"
33
34namespace llvm {
35
36template <typename ContextT>
37bool GenericCycle<ContextT>::contains(const GenericCycle *C) const {
38 // Containment check using the Euler tour representation.
39 return C && IdxBegin <= C->IdxBegin && C->IdxEnd <= IdxEnd;
40}
41
42template <typename ContextT>
44 return contains(CI->getCycle(Block));
45}
46
47template <typename ContextT>
49 return CI->BlockLayout.begin() + IdxBegin;
50}
51
52template <typename ContextT>
54 return CI->BlockLayout.begin() + IdxEnd;
55}
56
57template <typename ContextT>
59 SmallVectorImpl<BlockT *> &TmpStorage) const {
60 if (!ExitBlocksCache.empty()) {
61 TmpStorage.append(ExitBlocksCache.begin(), ExitBlocksCache.end());
62 return;
63 }
64
65 size_t NumExitBlocks = 0;
66 for (BlockT *Block : blocks()) {
67 llvm::append_range(ExitBlocksCache, successors(Block));
68
69 for (size_t Idx = NumExitBlocks, End = ExitBlocksCache.size(); Idx < End;
70 ++Idx) {
71 BlockT *Succ = ExitBlocksCache[Idx];
72 if (!contains(Succ)) {
73 auto ExitEndIt = ExitBlocksCache.begin() + NumExitBlocks;
74 if (std::find(ExitBlocksCache.begin(), ExitEndIt, Succ) == ExitEndIt)
75 ExitBlocksCache[NumExitBlocks++] = Succ;
76 }
77 }
78
79 ExitBlocksCache.resize(NumExitBlocks);
80 }
81
82 TmpStorage.append(ExitBlocksCache.begin(), ExitBlocksCache.end());
83}
84
85template <typename ContextT>
87 SmallVectorImpl<BlockT *> &TmpStorage) const {
88 for (BlockT *Block : blocks()) {
89 for (BlockT *Succ : successors(Block)) {
90 if (!contains(Succ)) {
91 TmpStorage.push_back(Block);
92 break;
93 }
94 }
95 }
96}
97
98template <typename ContextT>
100 BlockT *Predecessor = getCyclePredecessor();
101 if (!Predecessor)
102 return nullptr;
103
104 assert(isReducible() && "Cycle Predecessor must be in a reducible cycle!");
105
106 if (succ_size(Predecessor) != 1)
107 return nullptr;
108
109 // Make sure we are allowed to hoist instructions into the predecessor.
110 if (!Predecessor->isLegalToHoistInto())
111 return nullptr;
112
113 return Predecessor;
114}
115
116template <typename ContextT>
118 if (!isReducible())
119 return nullptr;
120
121 BlockT *Out = nullptr;
122
123 // Loop over the predecessors of the header node...
124 BlockT *Header = getHeader();
125 for (const auto Pred : predecessors(Header)) {
126 if (!contains(Pred)) {
127 if (Out && Out != Pred)
128 return nullptr;
129 Out = Pred;
130 }
131 }
132
133 return Out;
134}
135
136/// \brief Verify that this is actually a well-formed cycle in the CFG.
137template <typename ContextT> void GenericCycle<ContextT>::verifyCycle() const {
138#ifndef NDEBUG
139 assert(getNumBlocks() != 0 && "Cycle cannot be empty.");
140 DenseSet<BlockT *> Blocks;
141 for (BlockT *BB : blocks()) {
142 assert(Blocks.insert(BB).second); // duplicates in block list?
143 }
144 assert(!Entries.empty() && "Cycle must have one or more entries.");
145
146 DenseSet<BlockT *> Entries;
147 for (BlockT *Entry : entries()) {
148 assert(Entries.insert(Entry).second); // duplicate entry?
149 assert(contains(Entry));
150 }
151
152 // Setup for using a depth-first iterator to visit every block in the cycle.
154 getExitBlocks(ExitBBs);
156 VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
157
158 // Keep track of the BBs visited.
159 SmallPtrSet<BlockT *, 8> VisitedBBs;
160
161 // Check the individual blocks.
162 for (BlockT *BB : depth_first_ext(getHeader(), VisitSet)) {
164 [&](BlockT *B) { return contains(B); }) &&
165 "Cycle block has no in-cycle successors!");
166
168 [&](BlockT *B) { return contains(B); }) &&
169 "Cycle block has no in-cycle predecessors!");
170
171 DenseSet<BlockT *> OutsideCyclePreds;
173 if (!contains(B))
174 OutsideCyclePreds.insert(B);
175
176 if (Entries.contains(BB)) {
177 assert(!OutsideCyclePreds.empty() && "Entry is unreachable!");
178 } else if (!OutsideCyclePreds.empty()) {
179 // A non-entry block shouldn't be reachable from outside the cycle,
180 // though it is permitted if the predecessor is not itself actually
181 // reachable.
182 BlockT *EntryBB = &BB->getParent()->front();
183 for (BlockT *CB : depth_first(EntryBB))
184 assert(!OutsideCyclePreds.contains(CB) &&
185 "Non-entry block reachable from outside!");
186 }
187 assert(BB != &getHeader()->getParent()->front() &&
188 "Cycle contains function entry block!");
189
190 VisitedBBs.insert(BB);
191 }
192
193 if (VisitedBBs.size() != getNumBlocks()) {
194 dbgs() << "The following blocks are unreachable in the cycle:\n ";
195 ListSeparator LS;
196 for (auto *BB : Blocks) {
197 if (!VisitedBBs.count(BB)) {
198 dbgs() << LS;
199 BB->printAsOperand(dbgs());
200 }
201 }
202 dbgs() << "\n";
203 llvm_unreachable("Unreachable block in cycle");
204 }
205
207#endif
208}
209
210/// \brief Verify the parent-child relations of this cycle.
211///
212/// Note that this does \em not check that cycle is really a cycle in the CFG.
213template <typename ContextT>
215#ifndef NDEBUG
216 // Check the subcycles.
217 for (GenericCycle *Child : children()) {
218 // Each block in each subcycle should be contained within this cycle.
219 for (BlockT *BB : Child->blocks()) {
220 assert(contains(BB) &&
221 "Cycle does not contain all the blocks of a subcycle!");
222 }
223 assert(Child->Depth == Depth + 1);
224 }
225
226 // Check the parent cycle pointer.
227 if (ParentCycle) {
228 assert(is_contained(ParentCycle->children(), this) &&
229 "Cycle is not a subcycle of its parent!");
230 assert(ParentCycle->TopLevelCycle == TopLevelCycle &&
231 "Top level cycle of parent cycle must be the same");
232 } else {
233 assert(TopLevelCycle == this &&
234 "Cycle without parent must be top-level cycle");
235 }
236#endif
237}
238
239/// \brief Helper class for computing cycle information.
240template <typename ContextT> class GenericCycleInfoCompute {
241 using BlockT = typename ContextT::BlockT;
242 using FunctionT = typename ContextT::FunctionT;
243 using CycleInfoT = GenericCycleInfo<ContextT>;
244 using CycleT = typename CycleInfoT::CycleT;
245
246 CycleInfoT &Info;
247
248 struct DFSInfo {
249 unsigned Start = 0; // DFS start; positive if block is found
250 unsigned End = 0; // DFS end
251
252 DFSInfo() = default;
253 explicit DFSInfo(unsigned Start) : Start(Start) {}
254
255 explicit operator bool() const { return Start; }
256
257 /// Whether this node is an ancestor (or equal to) the node \p Other
258 /// in the DFS tree.
259 bool isAncestorOf(const DFSInfo &Other) const {
260 return Start <= Other.Start && Other.End <= End;
261 }
262 };
263
264 // Indexed by block number.
265 SmallVector<DFSInfo, 8> BlockDFSInfo;
266 SmallVector<BlockT *, 8> BlockPreorder;
267
268 GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
269 GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
270
271 DFSInfo getDFSInfo(BlockT *B) const {
273 return BlockDFSInfo[Number];
274 }
275
276 DFSInfo &getOrInsertDFSInfo(BlockT *B) {
278 return BlockDFSInfo[Number];
279 }
280
281public:
282 GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
283
284 void run(FunctionT *F);
285
286 static void updateDepth(CycleT *SubTree);
287
288private:
289 void dfs(FunctionT *F, BlockT *EntryBlock);
290};
291
292template <typename ContextT>
294 const BlockT *Block) const -> CycleT * {
296 return Cycle ? Cycle->TopLevelCycle : nullptr;
297}
298
299template <typename ContextT>
300void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
301 CycleT *Child) {
302 assert((!Child->ParentCycle && !NewParent->ParentCycle) &&
303 "NewParent and Child must be both top level cycle!\n");
304 auto &CurrentContainer =
305 Child->ParentCycle ? Child->ParentCycle->Children : TopLevelCycles;
306 auto Pos = llvm::find_if(CurrentContainer, [=](const auto &Ptr) -> bool {
307 return Child == Ptr.get();
308 });
309 assert(Pos != CurrentContainer.end());
310 NewParent->Children.push_back(std::move(*Pos));
311 *Pos = std::move(CurrentContainer.back());
312 CurrentContainer.pop_back();
313 Child->ParentCycle = NewParent;
314 Child->TopLevelCycle = NewParent;
315 for (CycleT *Cycle : depth_first(Child))
316 Cycle->TopLevelCycle = NewParent;
317 // This only relinks the cycle tree and does NOT touch BlockLayout, so it
318 // leaves every cycle's [IdxBegin, IdxEnd) range stale, i.e. BlockLayout is
319 // left invalid. The caller must call layoutBlocks() before any
320 // range-dependent query is used.
322
323template <typename ContextT>
324void GenericCycleInfo<ContextT>::verifyBlockNumberEpoch(
325 const FunctionT *Fn) const {
326 assert(BlockNumberEpoch ==
328 "CycleInfo used with outdated block number epoch");
331template <typename ContextT>
332void GenericCycleInfo<ContextT>::addToBlockMap(BlockT *Block, CycleT *Cycle) {
333 // The caller should ensure that BlockMap is large enough.
334 verifyBlockNumberEpoch(Block->getParent());
336 BlockMap[Number] = Cycle;
337}
338
339template <typename ContextT>
341 // Make sure BlockMap is large enough for the new block.
343 if (Number >= BlockMap.size())
344 BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(Block->getParent()));
345
346 // Insert Block at the end of Cycle's slice and shift every later cycle's
347 // range right. contain it below. The forest is an Euler tour, so a subtree
348 // ending at or before Pos is entirely earlier and is skipped.
349 unsigned Pos = Cycle->IdxEnd;
350 BlockLayout.insert(BlockLayout.begin() + Pos, Block);
352 while (!Worklist.empty()) {
353 CycleT *C = Worklist.pop_back_val();
354 if (C->IdxEnd <= Pos)
355 continue;
356 if (C->IdxBegin >= Pos) {
357 ++C->IdxBegin;
358 ++C->IdxEnd;
359 }
360 for (auto &Child : C->Children)
361 Worklist.push_back(Child.get());
362 }
363 addToBlockMap(Block, Cycle);
364 // Cycle and its ancestors gain the new block: extend each one's slice and
365 // invalidate its exit-block cache in a single walk up the tree.
366 for (CycleT *C = Cycle; C; C = C->getParentCycle()) {
367 ++C->IdxEnd;
368 C->clearCache();
369 }
370}
371
372template <typename ContextT>
373void GenericCycleInfo<ContextT>::layoutBlocks(ArrayRef<BlockT *> Order) {
374 if (TopLevelCycles.empty())
375 return;
376
377 // Walk the cycle forest as an Euler tour. On entry, a cycle's IdxEnd still
378 // holds its own-block count (accumulated during run()); reserve that many
379 // slots for its own region [Cursor, Cursor + count). Its children take the
380 // following slots, so on leaving, Cursor is the cycle's real range end, which
381 // overwrites the now-consumed count in IdxEnd.
382 struct Frame {
383 CycleT *C;
384 typename CycleT::const_child_iterator ChildCur, ChildEnd;
385 };
387 unsigned Cursor = 0;
388 auto enter = [&](CycleT *C) {
389 Cursor += C->IdxEnd; // IdxEnd currently holds C's own-block count.
390 C->IdxBegin = Cursor;
391 Stack.push_back({C, C->child_begin(), C->child_end()});
392 };
393 for (CycleT *TLC : toplevel_cycles()) {
394 enter(TLC);
395 while (!Stack.empty()) {
396 Frame &F = Stack.back();
397 if (F.ChildCur != F.ChildEnd) {
398 enter(*F.ChildCur++);
399 } else {
400 F.C->IdxEnd = Cursor;
401 Stack.pop_back();
402 }
403 }
404 }
405
406 // Place every block into its innermost cycle's own region.
407 BlockLayout.resize_for_overwrite(Cursor);
408 for (BlockT *B : llvm::reverse(Order))
409 if (CycleT *C = getCycle(B))
410 BlockLayout[--C->IdxBegin] = B;
411}
412
413/// \brief Main function of the cycle info computations.
414template <typename ContextT>
416 BlockT *EntryBlock = GraphTraits<FunctionT *>::getEntryNode(F);
417 LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock)
418 << "\n");
419 dfs(F, EntryBlock);
420
422
423 for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) {
424 const DFSInfo CandidateInfo = getDFSInfo(HeaderCandidate);
425
426 for (BlockT *Pred : predecessors(HeaderCandidate)) {
427 const DFSInfo PredDFSInfo = getDFSInfo(Pred);
428 // This automatically ignores unreachable predecessors since they have
429 // zeros in their DFSInfo.
430 if (CandidateInfo.isAncestorOf(PredDFSInfo))
431 Worklist.push_back(Pred);
432 }
433 if (Worklist.empty()) {
434 continue;
435 }
436
437 // Found a cycle with the candidate as its header.
438 LLVM_DEBUG(errs() << "Found cycle for header: "
439 << Info.Context.print(HeaderCandidate) << "\n");
440 std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>();
441 NewCycle->CI = &Info;
442 NewCycle->appendEntry(HeaderCandidate);
443 Info.addToBlockMap(HeaderCandidate, NewCycle.get());
444 // The header is this cycle's first own block. Until layoutBlocks runs,
445 // IdxEnd accumulates this cycle's own-block count (see the IdxBegin/
446 // IdxEnd doc comment), so layoutBlocks needs no separate counting pass.
447 ++NewCycle->IdxEnd;
448
449 // Helper function to process (non-back-edge) predecessors of a discovered
450 // block and either add them to the worklist or recognize that the given
451 // block is an additional cycle entry.
452 auto ProcessPredecessors = [&](BlockT *Block) {
453 LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": ");
454
455 bool IsEntry = false;
456 for (BlockT *Pred : predecessors(Block)) {
457 const DFSInfo PredDFSInfo = getDFSInfo(Pred);
458 if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
459 Worklist.push_back(Pred);
460 } else if (!PredDFSInfo) {
461 // Ignore an unreachable predecessor. It will will incorrectly cause
462 // Block to be treated as a cycle entry.
463 LLVM_DEBUG(errs() << " skipped unreachable predecessor.\n");
464 } else {
465 IsEntry = true;
466 }
467 }
468 if (IsEntry) {
469 assert(!NewCycle->isEntry(Block));
470 LLVM_DEBUG(errs() << "append as entry\n");
471 NewCycle->appendEntry(Block);
472 } else {
473 LLVM_DEBUG(errs() << "append as child\n");
474 }
475 };
476
477 do {
478 BlockT *Block = Worklist.pop_back_val();
479 if (Block == HeaderCandidate)
480 continue;
481
482 // If the block has already been discovered by some cycle
483 // (possibly by ourself), then the outermost cycle containing it
484 // should become our child.
485 if (auto *BlockParent = Info.getTopLevelParentCycle(Block)) {
486 LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": ");
487
488 if (BlockParent != NewCycle.get()) {
490 << "discovered child cycle "
491 << Info.Context.print(BlockParent->getHeader()) << "\n");
492 // Make BlockParent the child of NewCycle.
493 Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent);
494
495 for (auto *ChildEntry : BlockParent->entries())
496 ProcessPredecessors(ChildEntry);
497 } else {
499 << "known child cycle "
500 << Info.Context.print(BlockParent->getHeader()) << "\n");
501 }
502 } else {
503 Info.addToBlockMap(Block, NewCycle.get());
504 ++NewCycle->IdxEnd; // Block's innermost cycle is NewCycle.
505 ProcessPredecessors(Block);
506 }
507 } while (!Worklist.empty());
508
509 Info.TopLevelCycles.push_back(std::move(NewCycle));
510 }
511
512 // Fix top-level cycle links and compute cycle depths.
513 for (auto *TLC : Info.toplevel_cycles()) {
514 LLVM_DEBUG(errs() << "top-level cycle: "
515 << Info.Context.print(TLC->getHeader()) << "\n");
516
517 TLC->ParentCycle = nullptr;
518 updateDepth(TLC);
519 }
520
521 // The cycle tree and the block-to-innermost-cycle map are complete; lay out
522 // every cycle's blocks into the shared contiguous BlockLayout.
523 Info.layoutBlocks(BlockPreorder);
524}
525
526/// \brief Recompute depth values of \p SubTree and all descendants.
527template <typename ContextT>
529 for (CycleT *Cycle : depth_first(SubTree))
530 Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1;
531}
532
533/// \brief Compute a DFS of basic blocks starting at the function entry.
534///
535/// Fills BlockDFSInfo with start/end counters and BlockPreorder.
536template <typename ContextT>
537void GenericCycleInfoCompute<ContextT>::dfs(FunctionT *F, BlockT *EntryBlock) {
538 BlockDFSInfo.resize(GraphTraits<FunctionT *>::getMaxNumber(F));
539
540 // Successors are visited in reverse order to match the legacy
541 // single-LIFO-stack traversal, keeping cycle identification and block order
542 // unchanged.
543 using SuccIt = decltype(successors(EntryBlock).begin());
544 struct Frame {
545 BlockT *Block;
546 std::reverse_iterator<SuccIt> Cur, End;
547 };
549 unsigned Counter = 0;
550
551 auto open = [&](BlockT *Block) {
552 getOrInsertDFSInfo(Block).Start = ++Counter;
553 BlockPreorder.push_back(Block);
554 LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block)
555 << ", preorder number: " << Counter << "\n");
556 auto Succs = successors(Block);
557 Stack.push_back({Block, std::make_reverse_iterator(Succs.end()),
558 std::make_reverse_iterator(Succs.begin())});
559 };
560
561 open(EntryBlock);
562 while (!Stack.empty()) {
563 Frame &Top = Stack.back();
564 BlockT *Next = nullptr;
565 while (Top.Cur != Top.End) {
566 BlockT *Succ = *Top.Cur++;
567 if (getOrInsertDFSInfo(Succ).Start == 0) {
568 Next = Succ;
569 break;
570 }
571 LLVM_DEBUG(errs() << " already visited successor: "
572 << Info.Context.print(Succ) << "\n");
573 }
574 if (Next) {
575 open(Next);
576 } else {
577 // Top's subtree is complete. Its end counter is the largest preorder
578 // number in the subtree.
579 getOrInsertDFSInfo(Top.Block).End = Counter;
580 LLVM_DEBUG(errs() << "DFS block " << Info.Context.print(Top.Block)
581 << " ended at " << Counter << "\n");
582 Stack.pop_back();
583 }
584 }
585
586 LLVM_DEBUG({
587 errs() << "Preorder:\n";
588 for (int I = 0, E = BlockPreorder.size(); I != E; ++I)
589 errs() << " " << Info.Context.print(BlockPreorder[I]) << ": " << I
590 << "\n";
591 });
592}
593
594/// \brief Reset the object to its initial state.
595template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
596 TopLevelCycles.clear();
597 BlockMap.clear();
598 BlockLayout.clear();
599}
600
601/// \brief Compute the cycle info for a function.
602template <typename ContextT>
605 Context = ContextT(&F);
606 BlockNumberEpoch = GraphTraits<FunctionT *>::getNumberEpoch(&F);
607 BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(&F));
608
609 LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
610 << "\n");
611 Compute.run(&F);
612}
613
614template <typename ContextT>
616 BlockT *NewBlock) {
617 // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
618 // cycles that had blocks Pred and Succ also get NewBlock.
620 if (!Cycle)
621 return;
622
623 addBlockToCycle(NewBlock, Cycle);
625}
626
627/// \brief Find the innermost cycle containing a given block.
628///
629/// \returns the innermost cycle containing \p Block or nullptr if
630/// it is not contained in any cycle.
631template <typename ContextT>
633 -> CycleT * {
634 verifyBlockNumberEpoch(Block->getParent());
636 return Number < BlockMap.size() ? BlockMap[Number] : nullptr;
637}
638
639/// \brief Find the innermost cycle containing both given cycles.
640///
641/// \returns the innermost cycle containing both \p A and \p B
642/// or nullptr if there is no such cycle.
643template <typename ContextT>
645 CycleT *B) const
646 -> CycleT * {
647 if (!A || !B)
648 return nullptr;
649
650 // If cycles A and B have different depth replace them with parent cycle
651 // until they have the same depth.
652 while (A->getDepth() > B->getDepth())
653 A = A->getParentCycle();
654 while (B->getDepth() > A->getDepth())
655 B = B->getParentCycle();
656
657 // Cycles A and B are at same depth but may be disjoint, replace them with
658 // parent cycles until we find cycle that contains both or we run out of
659 // parent cycles.
660 while (A != B) {
661 A = A->getParentCycle();
662 B = B->getParentCycle();
663 }
664
665 return A;
666}
667
668/// \brief Find the innermost cycle containing both given blocks.
669///
670/// \returns the innermost cycle containing both \p A and \p B
671/// or nullptr if there is no such cycle.
672template <typename ContextT>
678
679/// \brief get the depth for the cycle which containing a given block.
680///
681/// \returns the depth for the innermost cycle containing \p Block or 0 if it is
682/// not contained in any cycle.
683template <typename ContextT>
686 if (!Cycle)
687 return 0;
688 return Cycle->getDepth();
689}
690
691/// \brief Verify the internal consistency of the cycle tree.
692///
693/// Note that this does \em not check that cycles are really cycles in the CFG,
694/// or that the right set of cycles in the CFG were found.
695template <typename ContextT>
697#ifndef NDEBUG
698 DenseSet<BlockT *> CycleHeaders;
699
700 for (CycleT *TopCycle : toplevel_cycles()) {
701 for (CycleT *Cycle : depth_first(TopCycle)) {
702 BlockT *Header = Cycle->getHeader();
703 assert(CycleHeaders.insert(Header).second);
704 if (VerifyFull)
705 Cycle->verifyCycle();
706 else
707 Cycle->verifyCycleNest();
708 // Check the block map entries for blocks contained in this cycle.
709 for (BlockT *BB : Cycle->blocks()) {
710 CycleT *CycleInBlockMap = getCycle(BB);
711 assert(CycleInBlockMap != nullptr);
712 assert(Cycle->contains(CycleInBlockMap));
713 }
714 }
715 }
716#endif
717}
718
719/// \brief Verify that the entire cycle tree well-formed.
720template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
721 verifyCycleNest(/*VerifyFull=*/true);
722}
723
724/// \brief Print the cycle info.
725template <typename ContextT>
727 for (const auto *TLC : toplevel_cycles()) {
728 for (const CycleT *Cycle : depth_first(TLC)) {
729 for (unsigned I = 0; I < Cycle->Depth; ++I)
730 Out << " ";
731
732 Out << Cycle->print(Context) << '\n';
733 }
734 }
735}
736
737} // namespace llvm
738
739#undef DEBUG_TYPE
740
741#endif // LLVM_ADT_GENERICCYCLEIMPL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static const Function * getParent(const Value *V)
bbsections Prepares for basic block by splitting functions into clusters of basic blocks
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
Find all cycles in a control-flow graph, including irreducible loops.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
GenericCycleInfoCompute(CycleInfoT &Info)
void run(FunctionT *F)
Main function of the cycle info computations.
static void updateDepth(CycleT *SubTree)
Recompute depth values of SubTree and all descendants.
Cycle information for a function.
typename ContextT::FunctionT FunctionT
void verify() const
Verify that the entire cycle tree well-formed.
void addBlockToCycle(BlockT *Block, CycleT *Cycle)
Assumes that Cycle is the innermost cycle containing Block.
iterator_range< const_toplevel_iterator > toplevel_cycles() const
CycleT * getTopLevelParentCycle(const BlockT *Block) const
friend class GenericCycleInfoCompute
void print(raw_ostream &Out) const
Print the cycle info.
CycleT * getSmallestCommonCycle(CycleT *A, CycleT *B) const
Find the innermost cycle containing both given cycles.
void clear()
Reset the object to its initial state.
GenericCycle< ContextT > CycleT
void compute(FunctionT &F)
Compute the cycle info for a function.
void splitCriticalEdge(BlockT *Pred, BlockT *Succ, BlockT *New)
unsigned getCycleDepth(const BlockT *Block) const
get the depth for the cycle which containing a given block.
void verifyCycleNest(bool VerifyFull=false) const
Methods for debug and self-test.
typename ContextT::BlockT BlockT
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
BlockT * getHeader() const
bool isReducible() const
Whether the cycle is a natural loop.
void getExitingBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of this cycle that have successor outside of this cycle.
const_block_iterator block_begin() const
void verifyCycle() const
Verify that this is actually a well-formed cycle in the CFG.
iterator_range< const_entry_iterator > entries() const
void verifyCycleNest() const
Verify the parent-child relations of this cycle.
BlockT * getCyclePreheader() const
Return the preheader block for this cycle.
void getExitBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all of the successor blocks of this cycle.
typename SmallVector< BlockT *, 8 >::const_iterator const_block_iterator
Iteration over blocks in the cycle (including entry blocks).
BlockT * getCyclePredecessor() const
If the cycle has exactly one entry with exactly one predecessor, return it, otherwise return nullptr.
bool contains(const BlockT *Block) const
Return whether Block is contained in the cycle. O(1).
const_block_iterator block_end() const
typename ContextT::BlockT BlockT
size_t getNumBlocks() const
A helper class to return the specified delimiter string after the first invocation of operator String...
size_type size() const
Definition SmallPtrSet.h:99
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
auto successors(const MachineBasicBlock *BB)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
CycleInfo::CycleT Cycle
Definition CycleInfo.h:26
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
auto succ_size(const MachineBasicBlock *BB)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Other
Any other memory.
Definition ModRef.h:68
iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
auto predecessors(const MachineBasicBlock *BB)
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
iterator_range< df_iterator< T > > depth_first(const T &G)
std::pair< iterator, bool > insert(NodeRef N)