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 "llvm/ADT/STLExtras.h"
32#include <iterator>
33
34#define DEBUG_TYPE "generic-cycle-impl"
35
36namespace llvm {
37
38template <typename ContextT>
40 CycleRef C, SmallVectorImpl<BlockT *> &TmpStorage) const {
41 if (ExitBlocksCaches.empty())
42 ExitBlocksCaches.resize(NumCycles);
43 auto &Cache = ExitBlocksCaches[C.Index];
44 if (Cache.empty()) {
46 for (BlockT *Block : getBlocks(C))
47 for (BlockT *Succ : successors(Block))
48 if (!contains(C, Succ) && Seen.insert(Succ).second)
49 Cache.push_back(Succ);
50 }
51 TmpStorage.append(Cache.begin(), Cache.end());
52}
53
54template <typename ContextT>
56 CycleRef C, SmallVectorImpl<BlockT *> &TmpStorage) const {
57 for (BlockT *Block : getBlocks(C)) {
58 for (BlockT *Succ : successors(Block)) {
59 if (!contains(C, Succ)) {
60 TmpStorage.push_back(Block);
61 break;
62 }
63 }
64 }
65}
66
67template <typename ContextT>
69 -> BlockT * {
70 BlockT *Predecessor = getCyclePredecessor(C);
71 if (!Predecessor)
72 return nullptr;
73
74 assert(isReducible(C) && "Cycle Predecessor must be in a reducible cycle!");
75
76 if (succ_size(Predecessor) != 1)
77 return nullptr;
78
79 // Make sure we are allowed to hoist instructions into the predecessor.
80 if (!Predecessor->isLegalToHoistInto())
81 return nullptr;
82
83 return Predecessor;
84}
85
86template <typename ContextT>
88 -> BlockT * {
89 if (!isReducible(C))
90 return nullptr;
91
92 BlockT *Out = nullptr;
93
94 // Loop over the predecessors of the header node...
95 BlockT *Header = getHeader(C);
96 for (const auto Pred : predecessors(Header)) {
97 if (!contains(C, Pred)) {
98 if (Out && Out != Pred)
99 return nullptr;
100 Out = Pred;
101 }
102 }
103
104 return Out;
105}
106
107template <typename ContextT>
109 CycleRef C, SmallPtrSetImpl<BlockT *> &Reachable) const {
110#ifndef NDEBUG
111 assert(getNumBlocks(C) != 0 && "Cycle cannot be empty.");
112 DenseSet<BlockT *> Blocks;
113 for (BlockT *BB : getBlocks(C)) {
114 assert(Blocks.insert(BB).second); // duplicates in block list?
115 }
116 assert(!getEntries(C).empty() && "Cycle must have one or more entries.");
117
118 DenseSet<BlockT *> Entries;
119 for (BlockT *Entry : getEntries(C)) {
120 assert(Entries.insert(Entry).second); // duplicate entry?
121 assert(contains(C, Entry));
122 }
123
124 // Setup for using a depth-first iterator to visit every block in the cycle.
126 getExitBlocks(C, ExitBBs);
128 VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
129
130 // Keep track of the BBs visited.
131 SmallPtrSet<BlockT *, 8> VisitedBBs;
132
133 // Check the individual blocks.
134 for (BlockT *BB : depth_first_ext(getHeader(C), VisitSet)) {
136 [&](BlockT *B) { return contains(C, B); }) &&
137 "Cycle block has no in-cycle successors!");
138
140 [&](BlockT *B) { return contains(C, B); }) &&
141 "Cycle block has no in-cycle predecessors!");
142
143 DenseSet<BlockT *> OutsideCyclePreds;
145 if (!contains(C, B))
146 OutsideCyclePreds.insert(B);
147
148 if (Entries.contains(BB)) {
149 assert(!OutsideCyclePreds.empty() && "Entry is unreachable!");
150 } else if (!OutsideCyclePreds.empty()) {
151 // A non-entry block shouldn't be reachable from outside the cycle,
152 // though it is permitted if the predecessor is not itself actually
153 // reachable. The entry block is always reachable, so an empty set means
154 // it has not been computed yet.
155 if (Reachable.empty())
156 for (BlockT *CB : depth_first(&BB->getParent()->front()))
157 Reachable.insert(CB);
158 for (BlockT *Pred : OutsideCyclePreds)
159 assert(!Reachable.contains(Pred) &&
160 "Non-entry block reachable from outside!");
161 }
162 assert(BB != &getHeader(C)->getParent()->front() &&
163 "Cycle contains function entry block!");
164
165 VisitedBBs.insert(BB);
166 }
167
168 if (VisitedBBs.size() != getNumBlocks(C)) {
169 dbgs() << "The following blocks are unreachable in the cycle:\n ";
170 ListSeparator LS;
171 for (auto *BB : Blocks) {
172 if (!VisitedBBs.count(BB)) {
173 dbgs() << LS;
174 BB->printAsOperand(dbgs());
175 }
176 }
177 dbgs() << "\n";
178 llvm_unreachable("Unreachable block in cycle");
179 }
180
182#endif
183}
184
185template <typename ContextT>
187#ifndef NDEBUG
188 const CycleT &Cyc = deref(C);
189 // Check the subcycles.
190 for (auto Child : children(C)) {
191 // Each block in each subcycle should be contained within this cycle.
192 for (BlockT *BB : getBlocks(Child)) {
194 "Cycle does not contain all the blocks of a subcycle!");
196 assert(deref(Child).Depth == Cyc.Depth + 1);
197 }
198
199 // Check the parent cycle.
200 if (Cyc.hasParent()) {
201 assert(is_contained(children(Cyc.Parent), C) &&
202 "Cycle is not a subcycle of its parent!");
203 }
204#endif
205}
206
207/// \brief Helper class for computing cycle information.
208template <typename ContextT> class GenericCycleInfoCompute {
209 using BlockT = typename ContextT::BlockT;
210 using FunctionT = typename ContextT::FunctionT;
211 using CycleInfoT = GenericCycleInfo<ContextT>;
212 using CycleT = typename CycleInfoT::CycleT;
213
214 CycleInfoT &Info;
215
216 // Sentinel header-preorder rank meaning "no cycle".
217 static constexpr unsigned NoCycle = ~0u;
218 // Sentinel block number meaning "no block".
219 static constexpr unsigned NoBlock = ~0u;
220
221 // Per-block state indexed by block number. All fields default to zero.
222 struct BlockInfo {
223 // The block this entry describes (non-null once visited by DFS), packed
224 // with a bit for whether it heads a loop.
226 union {
227 // (Live only during DFS) 1-based position on the current DFS path; 0 if
228 // off path.
229 unsigned Pos = 0;
230 // (Live after DFS) Header-preorder rank of the innermost
231 // loop containing this block (the loop it heads if IsHeader); NoCycle if
232 // none.
233 unsigned LoopIdx;
234 };
235 // Block number of the innermost loop header; NoBlock if none. Set to
236 // NoBlock by open() on first visit, then woven by tagLoopHeader.
237 unsigned LoopHeader = 0;
238
239 BlockT *getBlock() const { return BlockAndHeader.getPointer(); }
240 bool isHeader() const { return BlockAndHeader.getInt(); }
241 void setHeader() { BlockAndHeader.setInt(true); }
242 // An unvisited entry is all-zero,
243 bool visited() const { return BlockAndHeader.getOpaqueValue() != nullptr; }
244 };
245
246 // Per-cycle scratch built in run() and consumed by flatten(), keyed by
247 // header-preorder rank.
248 struct CycleBuild {
249 unsigned ChildHead;
250 unsigned NextSibling;
251 unsigned OwnCount;
252 };
253
254 SmallVector<BlockInfo, 8> BlockInfos;
255 // Reachable block numbers in DFS preorder.
257 // Number of loop headers found by dfs().
258 unsigned NumHeaders = 0;
259 // Records (header H, block B): an edge from outside re-enters the closed
260 // cycle headed by H at B, making B a non-header entry of it.
262
263 GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
264 GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
265
266 static unsigned num(const BlockT *B) {
268 }
269
270 BlockInfo &info(unsigned Number) { return BlockInfos[Number]; }
271
272 // Weave loop header \p H (and its own header chain) into the loop header
273 // chain of \p B, keeping the chain ordered from innermost to outermost by
274 // DFS-path position. Building this chain on the fly is why the algorithm
275 // needs no union-find (used in the Havlak algorithm) at all.
276 void tagLoopHeader(unsigned B, unsigned H) {
277 assert(H != NoBlock);
278 // Invariant: info(B).Pos >= info(H).Pos.
279 while (B != H) {
280 unsigned IH = info(B).LoopHeader;
281 if (IH == NoBlock) {
282 // B's chain ended: append the rest of H's chain.
283 info(B).LoopHeader = H;
284 return;
285 }
286 // Keep whichever candidate header is inner (larger DFS-path position).
287 if (info(IH).Pos >= info(H).Pos)
288 B = IH;
289 else {
290 info(B).LoopHeader = H;
291 B = H;
292 H = IH;
293 }
294 }
295 }
296
297 void dfs(BlockT *EntryBlock);
298 void flatten(ArrayRef<CycleBuild> Build, unsigned TopHead);
299
300public:
301 GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
302
304};
305
306template <typename ContextT>
307void GenericCycleInfo<ContextT>::addToBlockMap(BlockT *Block, CycleRef C) {
308 // The caller should ensure that BlockMap is large enough. C is a flat
309 // cycle, so its preorder index is well-defined.
310 verifyBlockNumberEpoch(Block->getParent());
312 BlockMap[Number] = C;
313}
315template <typename ContextT>
317 CycleT &Cyc = deref(C);
318 // Make sure BlockMap is large enough for the new block.
320 if (Number >= BlockMap.size())
321 BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(Block->getParent()),
322 CycleRef());
323
324 // Insert Block at the end of Cyc's slice and shift every later cycle's
325 // range right. Ranges straddling Pos belong to Cyc's ancestors and are
326 // extended below.
327 unsigned Pos = Cyc.IdxEnd;
328 BlockLayout.insert(BlockLayout.begin() + Pos, Block);
329 for (unsigned I = 0; I != NumCycles; ++I) {
330 CycleT &X = Cycles[I];
331 if (X.IdxBegin >= Pos) {
332 ++X.IdxBegin;
333 ++X.IdxEnd;
334 }
335 // An entry list sits either at IdxBegin or past the tour; both shift.
336 if (X.EntryBegin >= Pos)
337 ++X.EntryBegin;
338 }
339 addToBlockMap(Block, C);
340 // Cyc and its ancestors gain the new block: extend each one's slice.
341 for (CycleRef I = C; I; I = deref(I).Parent)
342 ++deref(I).IdxEnd;
343 // The new block may also have become an exit of a cycle that does not
344 // contain it, e.g. a child of Cyc whose exit edge was split.
345 ExitBlocksCaches.clear();
346}
347
348/// Lay the discovered cycle forest out into Info's flat preorder array: number
349/// the cycles in Euler-tour order, set each one's parent, depth and descendant
350/// count, place every block into its innermost cycle's region of BlockLayout,
351/// and fill BlockMap. \p Build is keyed by header-preorder rank.
352template <typename ContextT>
353void GenericCycleInfoCompute<ContextT>::flatten(ArrayRef<CycleBuild> Build,
354 unsigned TopHead) {
355 unsigned N = Build.size();
356 Info.NumCycles = N;
357 Info.Cycles = std::make_unique<CycleT[]>(N);
358
359 // Walk the cycle forest as an Euler tour. On entry a cycle reserves [Cursor,
360 // Cursor + OwnCount) for its own blocks (IdxBegin temporarily holds that
361 // region's end; the fill loop below walks it back down); its descendants take
362 // the following slots, so on exit Cursor is its IdxEnd.
363 SmallVector<unsigned, 8> FlatIdx(N);
364 struct Frame {
365 unsigned Flat;
366 unsigned Child; // Next child to enter, NoCycle once exhausted.
367 };
369 unsigned Cursor = 0, NextID = 0;
370 auto enter = [&](unsigned C, CycleRef Parent) {
371 unsigned ID = NextID++;
372 FlatIdx[C] = ID;
373 CycleT &Flat = Info.Cycles[ID];
374 Flat.Parent = Parent;
375 Flat.Depth = Parent ? Info.deref(Parent).Depth + 1 : 1;
376 // Initialize as one-element entry list (just the header).
377 Flat.EntryBegin = Cursor;
378 Flat.EntrySize = 1;
379 Cursor += Build[C].OwnCount;
380 Flat.IdxBegin = Cursor;
381 Stack.push_back({ID, Build[C].ChildHead});
382 };
383 for (auto TLC = TopHead; TLC != NoCycle; TLC = Build[TLC].NextSibling) {
384 enter(TLC, CycleRef());
385 while (!Stack.empty()) {
386 Frame &F = Stack.back();
387 if (F.Child != NoCycle) {
388 unsigned C = F.Child;
389 F.Child = Build[C].NextSibling;
390 enter(C, CycleRef(F.Flat));
391 } else {
392 CycleT &Flat = Info.Cycles[F.Flat];
393 Flat.IdxEnd = Cursor;
394 Flat.NumDescendants = NextID - F.Flat - 1;
395 Stack.pop_back();
396 }
397 }
398 }
399
400 // Place every block into its innermost cycle's own region.
401 Info.BlockLayout.resize_for_overwrite(Cursor);
402 for (unsigned N : llvm::reverse(Preorder)) {
403 BlockInfo &BI = info(N);
404 if (BI.LoopIdx == NoCycle)
405 continue;
406 unsigned Flat = FlatIdx[BI.LoopIdx];
407 Info.BlockMap[N] = CycleRef(Flat);
408 Info.BlockLayout[--Info.Cycles[Flat].IdxBegin] = BI.getBlock();
409 }
410}
411
412/// \brief Main function of the cycle info computations.
413template <typename ContextT>
415 BlockT *EntryBlock = GraphTraits<FunctionT *>::getEntryNode(F);
416 BlockInfos.assign(GraphTraits<FunctionT *>::getMaxNumber(F), BlockInfo{});
417
418 dfs(EntryBlock);
419 if (!NumHeaders)
420 return;
421
422 // Number the cycles by their header's preorder rank and resolve every
423 // block's innermost cycle in one pass: a block's LoopHeader is a DFS
424 // ancestor and so already numbered, and parents get smaller ranks than
425 // their children.
427 // Exact reserve so the Head reference below survives each push_back.
428 Build.reserve(NumHeaders);
429 unsigned TopHead = NoCycle;
430 for (unsigned N : Preorder) {
431 BlockInfo &BI = info(N);
432 if (BI.isHeader()) {
433 unsigned I = Build.size();
434 BI.LoopIdx = I;
435 unsigned &Head = BI.LoopHeader != NoBlock
436 ? Build[info(BI.LoopHeader).LoopIdx].ChildHead
437 : TopHead;
438 Build.push_back({NoCycle, Head, 1}); // OwnCount 1: the header.
439 Head = I;
440 LLVM_DEBUG(dbgs() << "Found cycle for header: "
441 << Info.Context.print(BI.getBlock()) << "\n");
442 } else if (BI.LoopHeader != NoBlock) {
443 BI.LoopIdx = info(BI.LoopHeader).LoopIdx;
444 ++Build[BI.LoopIdx].OwnCount;
445 } else {
446 BI.LoopIdx = NoCycle;
447 }
448 }
449 flatten(Build, TopHead);
450 if (Reentries.empty())
451 return;
452
453 // Add the non-header entries recorded during the DFS. Sorting by (header,
454 // block) groups each cycle's entries together and in block preorder; a block
455 // may re-enter a cycle via several edges, so skip duplicates. Each group
456 // opens an entry slice seeded with the header.
457 SmallVector<unsigned, 8> Rank(BlockInfos.size());
458 for (auto [R, N] : enumerate(Preorder))
459 Rank[N] = R;
460 for (auto &[H, B] : Reentries)
461 B = Rank[B];
462 llvm::sort(Reentries);
463 unsigned PrevH = NoBlock;
464 for (unsigned I = 0, E = Reentries.size(); I != E; ++I) {
465 if (I && Reentries[I] == Reentries[I - 1])
466 continue;
467 auto [H, R] = Reentries[I];
468 CycleT &Cyc = Info.deref(Info.BlockMap[H]);
469 if (H != PrevH) {
470 BlockT *Header = Info.BlockLayout[Cyc.EntryBegin];
471 Cyc.EntryBegin = Info.BlockLayout.size();
472 Info.BlockLayout.push_back(Header);
473 PrevH = H;
474 }
475 Info.BlockLayout.push_back(info(Preorder[R]).getBlock());
476 Cyc.EntrySize = Info.BlockLayout.size() - Cyc.EntryBegin;
477 }
478}
479
480/// Identify (possibly irreducible) loops using a single-pass DFS algorithm of
481/// "A New Algorithm for Identifying Loops in Decompilation" (SAS 2007). The
482/// cycle forest is then reconstructed from the per-block header tags.
483template <typename ContextT>
484void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
485 // Successors are visited in reverse order to match the legacy
486 // single-LIFO-stack traversal, keeping cycle identification and block order
487 // unchanged.
488 using SuccIt = decltype(successors(EntryBlock).begin());
489 struct Frame {
490 unsigned Block;
491 std::reverse_iterator<SuccIt> Cur, End;
492 };
494 unsigned Counter = 0;
495 Preorder.resize_for_overwrite(BlockInfos.size());
496
497 auto open = [&](BlockT *Block) {
498 unsigned N = num(Block);
499 Preorder[Counter] = N;
500 BlockInfo &BI = info(N);
501 BI.BlockAndHeader.setPointerAndInt(Block, false);
502 BI.Pos = ++Counter;
503 BI.LoopHeader = NoBlock;
504 auto Succs = successors(Block);
505 Stack.push_back({N, std::make_reverse_iterator(Succs.end()),
506 std::make_reverse_iterator(Succs.begin())});
507 };
508
509 open(EntryBlock);
510 while (!Stack.empty()) {
511 Frame &Top = Stack.back();
512 if (Top.Cur != Top.End) {
513 unsigned B0 = Top.Block;
514 BlockT *B1P = *Top.Cur++;
515 unsigned B1 = num(B1P);
516 BlockInfo &B1Info = info(B1);
517 if (!B1Info.visited()) {
518 // Tree edge; the weaving happens when B1's frame is popped.
519 open(B1P);
520 } else if (B1Info.Pos > 0) {
521 // B1 is a loop header (including self-edge).
522 if (!B1Info.isHeader()) {
523 B1Info.setHeader();
524 ++NumHeaders;
525 }
526 tagLoopHeader(B0, B1);
527 } else {
528 // Climb B1's header chain: each enclosing header still off the DFS path
529 // heads a closed cycle this edge re-enters, so B1 is a non-header entry
530 // of it (and it is irreducible). Stop at the first on-path header and
531 // attribute B0 to it.
532 for (unsigned H = B1Info.LoopHeader; H != NoBlock;
533 H = info(H).LoopHeader) {
534 if (info(H).Pos > 0) {
535 tagLoopHeader(B0, H);
536 break;
537 }
538 Reentries.push_back({H, B1});
539 }
540 }
541 } else {
542 // Leave the DFS path.
543 unsigned B0 = Top.Block;
544 info(B0).Pos = 0;
545 Stack.pop_back();
546 // And weave into the parent's chain (continue the "Tree edge" case).
547 if (!Stack.empty() && info(B0).LoopHeader != NoBlock)
548 tagLoopHeader(Stack.back().Block, info(B0).LoopHeader);
549 }
550 }
551 Preorder.truncate(Counter);
552}
553
554/// \brief Reset the object to its initial state.
555template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
556 BlockMap.clear();
557 BlockLayout.clear();
558 Cycles.reset();
559 NumCycles = 0;
560 ExitBlocksCaches.clear();
561}
562
563/// \brief Compute the cycle info for a function.
564template <typename ContextT>
567 Context = ContextT(&F);
568 BlockNumberEpoch = GraphTraits<FunctionT *>::getNumberEpoch(&F);
570
571 LLVM_DEBUG(dbgs() << "Computing cycles for function: " << F.getName()
572 << "\n");
573 Compute.run(&F);
574}
575
576template <typename ContextT>
578 BlockT *NewBlock) {
579 // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
580 // cycles that had blocks Pred and Succ also get NewBlock. Any cycle that
581 // contains Pred but not Succ now exits to NewBlock instead of Succ.
582 ExitBlocksCaches.clear();
584 if (!C)
585 return;
586
587 addBlockToCycle(NewBlock, C);
589}
590
591/// \brief Find the innermost cycle containing both given cycles.
592///
593/// \returns the innermost cycle containing both \p A and \p B
594/// or nullptr if there is no such cycle.
595template <typename ContextT>
597 CycleRef B) const
598 -> CycleRef {
599 if (!A || !B)
600 return CycleRef();
601
602 // If cycles A and B have different depth replace them with parent cycle
603 // until they have the same depth.
604 while (getDepth(A) > getDepth(B))
605 A = getParentCycle(A);
606 while (getDepth(B) > getDepth(A))
607 B = getParentCycle(B);
608
609 // Cycles A and B are at same depth but may be disjoint, replace them with
610 // parent cycles until we find cycle that contains both or we run out of
611 // parent cycles.
612 while (A != B) {
613 A = getParentCycle(A);
614 B = getParentCycle(B);
615 }
616
617 return A;
618}
619
620/// \brief Find the innermost cycle containing both given blocks.
621///
622/// \returns the innermost cycle containing both \p A and \p B
623/// or nullptr if there is no such cycle.
624template <typename ContextT>
630
631/// \brief Verify the internal consistency of the cycle tree.
632///
633/// Note that this does \em not check that cycles are really cycles in the CFG,
634/// or that the right set of cycles in the CFG were found.
635template <typename ContextT>
637#ifndef NDEBUG
638 DenseSet<BlockT *> CycleHeaders;
640
641 for (auto C : cycles()) {
642 BlockT *Header = getHeader(C);
643 assert(CycleHeaders.insert(Header).second);
644 if (VerifyFull)
645 verifyCycle(C, Reachable);
646 else
648 // Check the block map entries for blocks contained in this cycle.
649 for (BlockT *BB : getBlocks(C)) {
650 CycleRef InBlockMap = getCycle(BB);
651 assert(InBlockMap.isValid());
652 assert(contains(C, InBlockMap));
653 }
654 }
655#endif
656}
657
658/// \brief Verify that the entire cycle tree well-formed.
659template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
660 verifyCycleNest(/*VerifyFull=*/true);
661}
662
663/// \brief Print the cycle info.
664template <typename ContextT>
666 for (auto C : cycles()) {
667 for (unsigned I = 0, Depth = getDepth(C); I < Depth; ++I)
668 Out << " ";
669
670 Out << print(C) << '\n';
671 }
672}
673
674/// \brief Print a single cycle: its depth, entries, and remaining blocks.
675template <typename ContextT>
677 return Printable([this, C](raw_ostream &Out) {
678 Out << "depth=" << getDepth(C) << ": entries(" << printEntries(C, Context)
679 << ')';
680
681 for (auto *Block : getBlocks(C)) {
682 if (isEntry(C, Block))
683 continue;
684
685 Out << ' ' << Context.print(Block);
686 }
687 });
688}
689
690} // namespace llvm
691
692#undef DEBUG_TYPE
693
694#endif // LLVM_ADT_GENERICCYCLEIMPL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
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.
lazy value info
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
This file defines the PointerIntPair class.
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
bool isValid() const
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.
Cycle information for a function.
typename SSAContext::FunctionT FunctionT
void verify() const
Verify that the entire cycle tree well-formed.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
bool isReducible(CycleRef C) const
BlockT * getCyclePreheader(CycleRef C) const
Return the preheader block for C.
CycleRef getSmallestCommonCycle(CycleRef A, CycleRef B) const
Find the innermost cycle containing both given cycles.
CycleRef getParentCycle(CycleRef C) const
BlockT * getCyclePredecessor(CycleRef C) const
If C has exactly one entry with exactly one predecessor, return it, otherwise return nullptr.
friend class GenericCycleInfoCompute
void verifyCycleNest(CycleRef C) const
Verify the parent-child relations of C.
void verifyCycle(CycleRef C, SmallPtrSetImpl< BlockT * > &Reachable) const
Verify that C is actually a well-formed cycle in the CFG.
void print(raw_ostream &Out) const
Print the cycle info.
ArrayRef< BlockT * > getEntries(CycleRef C) const
void clear()
Reset the object to its initial state.
void addBlockToCycle(BlockT *Block, CycleRef C)
Assumes that C is the innermost cycle containing Block.
ArrayRef< BlockT * > getBlocks(CycleRef C) const
Return the blocks of C, including those of nested cycles.
Printable printEntries(CycleRef C, const ContextT &Ctx) const
unsigned getDepth(CycleRef C) const
void compute(FunctionT &F)
Compute the cycle info for a function.
void splitCriticalEdge(BlockT *Pred, BlockT *Succ, BlockT *New)
void getExitBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all of the successor blocks of C: the blocks outside of C which are branched to from within it...
size_t getNumBlocks(CycleRef C) const
bool isEntry(CycleRef C, const BlockT *Block) const
BlockT * getHeader(CycleRef C) const
typename ContextT::BlockT BlockT
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
A helper class to return the specified delimiter string after the first invocation of operator String...
PointerIntPair - This class implements a pair of a pointer and small integer.
IntType getInt() const
void setInt(IntType IntVal) &
void * getOpaqueValue() const
PointerTy getPointer() const
Simple wrapper around std::function<void(raw_ostream&)>.
Definition Printable.h:38
size_type size() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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 resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void truncate(size_type N)
Like resize, but requires that N is less than size().
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
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
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.
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)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
auto successors(const MachineBasicBlock *BB)
static bool isHeader(StringRef S)
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:1762
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
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...
iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)
ArrayRef(const T &OneElt) -> ArrayRef< T >
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:1963
iterator_range< df_iterator< T > > depth_first(const T &G)
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
#define N
Binary functor that adapts to any other binary functor after dereferencing operands.
Definition STLExtras.h:2358
std::pair< iterator, bool > insert(NodeRef N)