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#ifndef NDEBUG
110 assert(getNumBlocks(C) != 0 && "Cycle cannot be empty.");
111 DenseSet<BlockT *> Blocks;
112 for (BlockT *BB : getBlocks(C)) {
113 assert(Blocks.insert(BB).second); // duplicates in block list?
114 }
115 assert(!getEntries(C).empty() && "Cycle must have one or more entries.");
116
117 DenseSet<BlockT *> Entries;
118 for (BlockT *Entry : getEntries(C)) {
119 assert(Entries.insert(Entry).second); // duplicate entry?
120 assert(contains(C, Entry));
121 }
122
123 // Setup for using a depth-first iterator to visit every block in the cycle.
125 getExitBlocks(C, ExitBBs);
127 VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
128
129 // Keep track of the BBs visited.
130 SmallPtrSet<BlockT *, 8> VisitedBBs;
131
132 // Check the individual blocks.
133 for (BlockT *BB : depth_first_ext(getHeader(C), VisitSet)) {
135 [&](BlockT *B) { return contains(C, B); }) &&
136 "Cycle block has no in-cycle successors!");
137
139 [&](BlockT *B) { return contains(C, B); }) &&
140 "Cycle block has no in-cycle predecessors!");
141
142 DenseSet<BlockT *> OutsideCyclePreds;
144 if (!contains(C, B))
145 OutsideCyclePreds.insert(B);
146
147 if (Entries.contains(BB)) {
148 assert(!OutsideCyclePreds.empty() && "Entry is unreachable!");
149 } else if (!OutsideCyclePreds.empty()) {
150 // A non-entry block shouldn't be reachable from outside the cycle,
151 // though it is permitted if the predecessor is not itself actually
152 // reachable.
153 BlockT *EntryBB = &BB->getParent()->front();
154 for (BlockT *CB : depth_first(EntryBB))
155 assert(!OutsideCyclePreds.contains(CB) &&
156 "Non-entry block reachable from outside!");
157 }
158 assert(BB != &getHeader(C)->getParent()->front() &&
159 "Cycle contains function entry block!");
160
161 VisitedBBs.insert(BB);
162 }
163
164 if (VisitedBBs.size() != getNumBlocks(C)) {
165 dbgs() << "The following blocks are unreachable in the cycle:\n ";
166 ListSeparator LS;
167 for (auto *BB : Blocks) {
168 if (!VisitedBBs.count(BB)) {
169 dbgs() << LS;
170 BB->printAsOperand(dbgs());
171 }
172 }
173 dbgs() << "\n";
174 llvm_unreachable("Unreachable block in cycle");
175 }
176
178#endif
179}
180
181template <typename ContextT>
183#ifndef NDEBUG
184 const CycleT &Cyc = deref(C);
185 // Check the subcycles.
186 for (auto Child : children(C)) {
187 // Each block in each subcycle should be contained within this cycle.
188 for (BlockT *BB : getBlocks(Child)) {
189 assert(contains(C, BB) &&
190 "Cycle does not contain all the blocks of a subcycle!");
192 assert(deref(Child).Depth == Cyc.Depth + 1);
194
195 // Check the parent cycle.
196 if (Cyc.hasParent()) {
197 assert(is_contained(children(Cyc.Parent), C) &&
198 "Cycle is not a subcycle of its parent!");
199 }
200#endif
201}
202
203/// \brief Helper class for computing cycle information.
204template <typename ContextT> class GenericCycleInfoCompute {
205 using BlockT = typename ContextT::BlockT;
206 using FunctionT = typename ContextT::FunctionT;
207 using CycleInfoT = GenericCycleInfo<ContextT>;
208 using CycleT = typename CycleInfoT::CycleT;
209
210 CycleInfoT &Info;
211
212 // Sentinel header-preorder rank meaning "no cycle".
213 static constexpr unsigned NoCycle = ~0u;
214 // Sentinel block number meaning "no block".
215 static constexpr unsigned NoBlock = ~0u;
216
217 // Per-block state indexed by block number. All fields default to zero.
218 struct BlockInfo {
219 // The block this entry describes (non-null once visited by DFS), packed
220 // with a bit for whether it heads a loop.
222 union {
223 // (Live only during DFS) 1-based position on the current DFS path; 0 if
224 // off path.
225 unsigned Pos = 0;
226 // (Live after DFS) Header-preorder rank of the innermost
227 // loop containing this block (the loop it heads if IsHeader); NoCycle if
228 // none.
229 unsigned LoopIdx;
230 };
231 // Block number of the innermost loop header; NoBlock if none. Set to
232 // NoBlock by open() on first visit, then woven by tagLoopHeader.
233 unsigned LoopHeader = 0;
234
235 BlockT *getBlock() const { return BlockAndHeader.getPointer(); }
236 bool isHeader() const { return BlockAndHeader.getInt(); }
237 void setHeader() { BlockAndHeader.setInt(true); }
238 // An unvisited entry is all-zero,
239 bool visited() const { return BlockAndHeader.getOpaqueValue() != nullptr; }
240 };
241
242 // Per-cycle scratch built in run() and consumed by flatten(), keyed by
243 // header-preorder rank.
244 struct CycleBuild {
245 unsigned ChildHead;
246 unsigned NextSibling;
247 unsigned OwnCount;
248 };
249
250 SmallVector<BlockInfo, 8> BlockInfos;
251 // Reachable block numbers in DFS preorder.
253 // Number of loop headers found by dfs().
254 unsigned NumHeaders = 0;
255 // Records (header H, block B): an edge from outside re-enters the closed
256 // cycle headed by H at B, making B a non-header entry of it.
258
259 GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
260 GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
261
262 static unsigned num(const BlockT *B) {
264 }
265
266 BlockInfo &info(unsigned Number) { return BlockInfos[Number]; }
267
268 // Weave loop header \p H (and its own header chain) into the loop header
269 // chain of \p B, keeping the chain ordered from innermost to outermost by
270 // DFS-path position. Building this chain on the fly is why the algorithm
271 // needs no union-find (used in the Havlak algorithm) at all.
272 void tagLoopHeader(unsigned B, unsigned H) {
273 assert(H != NoBlock);
274 // Invariant: info(B).Pos >= info(H).Pos.
275 while (B != H) {
276 unsigned IH = info(B).LoopHeader;
277 if (IH == NoBlock) {
278 // B's chain ended: append the rest of H's chain.
279 info(B).LoopHeader = H;
280 return;
281 }
282 // Keep whichever candidate header is inner (larger DFS-path position).
283 if (info(IH).Pos >= info(H).Pos)
284 B = IH;
285 else {
286 info(B).LoopHeader = H;
287 B = H;
288 H = IH;
289 }
290 }
291 }
292
293 void dfs(BlockT *EntryBlock);
294 void flatten(ArrayRef<CycleBuild> Build, unsigned TopHead);
295
296public:
297 GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
299 void run(FunctionT *F);
300};
302template <typename ContextT>
303void GenericCycleInfo<ContextT>::addToBlockMap(BlockT *Block, CycleRef C) {
304 // The caller should ensure that BlockMap is large enough. C is a flat
305 // cycle, so its preorder index is well-defined.
306 verifyBlockNumberEpoch(Block->getParent());
308 BlockMap[Number] = C;
309}
310
311template <typename ContextT>
313 CycleT &Cyc = deref(C);
314 // Make sure BlockMap is large enough for the new block.
316 if (Number >= BlockMap.size())
317 BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(Block->getParent()),
318 CycleRef());
319
320 // Insert Block at the end of Cyc's slice and shift every later cycle's
321 // range right. Ranges straddling Pos belong to Cyc's ancestors and are
322 // extended below.
323 unsigned Pos = Cyc.IdxEnd;
324 BlockLayout.insert(BlockLayout.begin() + Pos, Block);
325 for (unsigned I = 0; I != NumCycles; ++I) {
326 CycleT &X = Cycles[I];
327 if (X.IdxBegin >= Pos) {
328 ++X.IdxBegin;
329 ++X.IdxEnd;
331 // An entry list sits either at IdxBegin or past the tour; both shift.
332 if (X.EntryBegin >= Pos)
333 ++X.EntryBegin;
334 }
335 addToBlockMap(Block, C);
336 // Cyc and its ancestors gain the new block: extend each one's slice and
337 // invalidate its exit-block cache in a single walk up the tree.
338 for (CycleRef I = C; I; I = deref(I).Parent) {
339 ++deref(I).IdxEnd;
340 if (!ExitBlocksCaches.empty())
341 ExitBlocksCaches[I.Index].clear();
342 }
343}
344
345/// Lay the discovered cycle forest out into Info's flat preorder array: number
346/// the cycles in Euler-tour order, set each one's parent, depth and descendant
347/// count, place every block into its innermost cycle's region of BlockLayout,
348/// and fill BlockMap. \p Build is keyed by header-preorder rank.
349template <typename ContextT>
350void GenericCycleInfoCompute<ContextT>::flatten(ArrayRef<CycleBuild> Build,
351 unsigned TopHead) {
352 unsigned N = Build.size();
353 Info.NumCycles = N;
354 Info.Cycles = std::make_unique<CycleT[]>(N);
355
356 // Walk the cycle forest as an Euler tour. On entry a cycle reserves [Cursor,
357 // Cursor + OwnCount) for its own blocks (IdxBegin temporarily holds that
358 // region's end; the fill loop below walks it back down); its descendants take
359 // the following slots, so on exit Cursor is its IdxEnd.
361 struct Frame {
362 unsigned Flat;
363 unsigned Child; // Next child to enter, NoCycle once exhausted.
364 };
366 unsigned Cursor = 0, NextID = 0;
367 auto enter = [&](unsigned C, CycleRef Parent) {
368 unsigned ID = NextID++;
369 FlatIdx[C] = ID;
370 CycleT &Flat = Info.Cycles[ID];
371 Flat.Parent = Parent;
372 Flat.Depth = Parent ? Info.deref(Parent).Depth + 1 : 1;
373 // Initialize as one-element entry list (just the header).
374 Flat.EntryBegin = Cursor;
375 Flat.EntrySize = 1;
376 Cursor += Build[C].OwnCount;
377 Flat.IdxBegin = Cursor;
378 Stack.push_back({ID, Build[C].ChildHead});
379 };
380 for (auto TLC = TopHead; TLC != NoCycle; TLC = Build[TLC].NextSibling) {
381 enter(TLC, CycleRef());
382 while (!Stack.empty()) {
383 Frame &F = Stack.back();
384 if (F.Child != NoCycle) {
385 unsigned C = F.Child;
386 F.Child = Build[C].NextSibling;
387 enter(C, CycleRef(F.Flat));
388 } else {
389 CycleT &Flat = Info.Cycles[F.Flat];
390 Flat.IdxEnd = Cursor;
391 Flat.NumDescendants = NextID - F.Flat - 1;
392 Stack.pop_back();
393 }
394 }
395 }
396
397 // Place every block into its innermost cycle's own region.
398 Info.BlockLayout.resize_for_overwrite(Cursor);
399 for (unsigned N : llvm::reverse(Preorder)) {
400 BlockInfo &BI = info(N);
401 if (BI.LoopIdx == NoCycle)
402 continue;
403 unsigned Flat = FlatIdx[BI.LoopIdx];
404 Info.BlockMap[N] = CycleRef(Flat);
405 Info.BlockLayout[--Info.Cycles[Flat].IdxBegin] = BI.getBlock();
406 }
407}
408
409/// \brief Main function of the cycle info computations.
410template <typename ContextT>
412 BlockT *EntryBlock = GraphTraits<FunctionT *>::getEntryNode(F);
413 BlockInfos.assign(GraphTraits<FunctionT *>::getMaxNumber(F), BlockInfo{});
414
415 dfs(EntryBlock);
416 if (!NumHeaders)
417 return;
418
419 // Number the cycles by their header's preorder rank and resolve every
420 // block's innermost cycle in one pass: a block's LoopHeader is a DFS
421 // ancestor and so already numbered, and parents get smaller ranks than
422 // their children.
424 // Exact reserve so the Head reference below survives each push_back.
425 Build.reserve(NumHeaders);
426 unsigned TopHead = NoCycle;
427 for (unsigned N : Preorder) {
428 BlockInfo &BI = info(N);
429 if (BI.isHeader()) {
430 unsigned I = Build.size();
431 BI.LoopIdx = I;
432 unsigned &Head = BI.LoopHeader != NoBlock
433 ? Build[info(BI.LoopHeader).LoopIdx].ChildHead
434 : TopHead;
435 Build.push_back({NoCycle, Head, 1}); // OwnCount 1: the header.
436 Head = I;
437 LLVM_DEBUG(dbgs() << "Found cycle for header: "
438 << Info.Context.print(BI.getBlock()) << "\n");
439 } else if (BI.LoopHeader != NoBlock) {
440 BI.LoopIdx = info(BI.LoopHeader).LoopIdx;
441 ++Build[BI.LoopIdx].OwnCount;
442 } else {
443 BI.LoopIdx = NoCycle;
444 }
445 }
446 flatten(Build, TopHead);
447 if (Reentries.empty())
448 return;
449
450 // Add the non-header entries recorded during the DFS. Sorting by (header,
451 // block) groups each cycle's entries together and in block preorder; a block
452 // may re-enter a cycle via several edges, so skip duplicates. Each group
453 // opens an entry slice seeded with the header.
454 SmallVector<unsigned, 8> Rank(BlockInfos.size());
455 for (auto [R, N] : enumerate(Preorder))
456 Rank[N] = R;
457 for (auto &[H, B] : Reentries)
458 B = Rank[B];
459 llvm::sort(Reentries);
460 unsigned PrevH = NoBlock;
461 for (unsigned I = 0, E = Reentries.size(); I != E; ++I) {
462 if (I && Reentries[I] == Reentries[I - 1])
463 continue;
464 auto [H, R] = Reentries[I];
465 CycleT &Cyc = Info.deref(Info.BlockMap[H]);
466 if (H != PrevH) {
467 BlockT *Header = Info.BlockLayout[Cyc.EntryBegin];
468 Cyc.EntryBegin = Info.BlockLayout.size();
469 Info.BlockLayout.push_back(Header);
470 PrevH = H;
471 }
472 Info.BlockLayout.push_back(info(Preorder[R]).getBlock());
473 Cyc.EntrySize = Info.BlockLayout.size() - Cyc.EntryBegin;
474 }
475}
476
477/// Identify (possibly irreducible) loops using a single-pass DFS algorithm of
478/// "A New Algorithm for Identifying Loops in Decompilation" (SAS 2007). The
479/// cycle forest is then reconstructed from the per-block header tags.
480template <typename ContextT>
481void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
482 // Successors are visited in reverse order to match the legacy
483 // single-LIFO-stack traversal, keeping cycle identification and block order
484 // unchanged.
485 using SuccIt = decltype(successors(EntryBlock).begin());
486 struct Frame {
487 unsigned Block;
488 std::reverse_iterator<SuccIt> Cur, End;
489 };
491 unsigned Counter = 0;
492 Preorder.resize_for_overwrite(BlockInfos.size());
493
494 auto open = [&](BlockT *Block) {
495 unsigned N = num(Block);
496 Preorder[Counter] = N;
497 BlockInfo &BI = info(N);
498 BI.BlockAndHeader.setPointerAndInt(Block, false);
499 BI.Pos = ++Counter;
500 BI.LoopHeader = NoBlock;
501 auto Succs = successors(Block);
502 Stack.push_back({N, std::make_reverse_iterator(Succs.end()),
503 std::make_reverse_iterator(Succs.begin())});
504 };
505
506 open(EntryBlock);
507 while (!Stack.empty()) {
508 Frame &Top = Stack.back();
509 if (Top.Cur != Top.End) {
510 unsigned B0 = Top.Block;
511 BlockT *B1P = *Top.Cur++;
512 unsigned B1 = num(B1P);
513 BlockInfo &B1Info = info(B1);
514 if (!B1Info.visited()) {
515 // Tree edge; the weaving happens when B1's frame is popped.
516 open(B1P);
517 } else if (B1Info.Pos > 0) {
518 // B1 is a loop header (including self-edge).
519 if (!B1Info.isHeader()) {
520 B1Info.setHeader();
521 ++NumHeaders;
522 }
523 tagLoopHeader(B0, B1);
524 } else {
525 // Climb B1's header chain: each enclosing header still off the DFS path
526 // heads a closed cycle this edge re-enters, so B1 is a non-header entry
527 // of it (and it is irreducible). Stop at the first on-path header and
528 // attribute B0 to it.
529 for (unsigned H = B1Info.LoopHeader; H != NoBlock;
530 H = info(H).LoopHeader) {
531 if (info(H).Pos > 0) {
532 tagLoopHeader(B0, H);
533 break;
534 }
535 Reentries.push_back({H, B1});
536 }
537 }
538 } else {
539 // Leave the DFS path.
540 unsigned B0 = Top.Block;
541 info(B0).Pos = 0;
542 Stack.pop_back();
543 // And weave into the parent's chain (continue the "Tree edge" case).
544 if (!Stack.empty() && info(B0).LoopHeader != NoBlock)
545 tagLoopHeader(Stack.back().Block, info(B0).LoopHeader);
546 }
547 }
548 Preorder.truncate(Counter);
549}
550
551/// \brief Reset the object to its initial state.
552template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
553 BlockMap.clear();
554 BlockLayout.clear();
555 Cycles.reset();
556 NumCycles = 0;
557 ExitBlocksCaches.clear();
558}
559
560/// \brief Compute the cycle info for a function.
561template <typename ContextT>
564 Context = ContextT(&F);
565 BlockNumberEpoch = GraphTraits<FunctionT *>::getNumberEpoch(&F);
567
568 LLVM_DEBUG(dbgs() << "Computing cycles for function: " << F.getName()
569 << "\n");
570 Compute.run(&F);
571}
572
573template <typename ContextT>
575 BlockT *NewBlock) {
576 // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
577 // cycles that had blocks Pred and Succ also get NewBlock.
579 if (!C)
580 return;
581
582 addBlockToCycle(NewBlock, C);
584}
585
586/// \brief Find the innermost cycle containing both given cycles.
587///
588/// \returns the innermost cycle containing both \p A and \p B
589/// or nullptr if there is no such cycle.
590template <typename ContextT>
592 CycleRef B) const
593 -> CycleRef {
594 if (!A || !B)
595 return CycleRef();
596
597 // If cycles A and B have different depth replace them with parent cycle
598 // until they have the same depth.
599 while (getDepth(A) > getDepth(B))
600 A = getParentCycle(A);
601 while (getDepth(B) > getDepth(A))
602 B = getParentCycle(B);
603
604 // Cycles A and B are at same depth but may be disjoint, replace them with
605 // parent cycles until we find cycle that contains both or we run out of
606 // parent cycles.
607 while (A != B) {
608 A = getParentCycle(A);
609 B = getParentCycle(B);
610 }
611
612 return A;
613}
614
615/// \brief Find the innermost cycle containing both given blocks.
616///
617/// \returns the innermost cycle containing both \p A and \p B
618/// or nullptr if there is no such cycle.
619template <typename ContextT>
625
626/// \brief Verify the internal consistency of the cycle tree.
627///
628/// Note that this does \em not check that cycles are really cycles in the CFG,
629/// or that the right set of cycles in the CFG were found.
630template <typename ContextT>
632#ifndef NDEBUG
633 DenseSet<BlockT *> CycleHeaders;
634
635 for (auto C : cycles()) {
636 BlockT *Header = getHeader(C);
637 assert(CycleHeaders.insert(Header).second);
638 if (VerifyFull)
639 verifyCycle(C);
640 else
642 // Check the block map entries for blocks contained in this cycle.
643 for (BlockT *BB : getBlocks(C)) {
644 CycleRef InBlockMap = getCycle(BB);
645 assert(InBlockMap.isValid());
646 assert(contains(C, InBlockMap));
647 }
648 }
649#endif
650}
651
652/// \brief Verify that the entire cycle tree well-formed.
653template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
654 verifyCycleNest(/*VerifyFull=*/true);
655}
656
657/// \brief Print the cycle info.
658template <typename ContextT>
660 for (auto C : cycles()) {
661 for (unsigned I = 0, Depth = getDepth(C); I < Depth; ++I)
662 Out << " ";
663
664 Out << print(C) << '\n';
665 }
666}
667
668/// \brief Print a single cycle: its depth, entries, and remaining blocks.
669template <typename ContextT>
671 return Printable([this, C](raw_ostream &Out) {
672 Out << "depth=" << getDepth(C) << ": entries(" << printEntries(C, Context)
673 << ')';
674
675 for (auto *Block : getBlocks(C)) {
676 if (isEntry(C, Block))
677 continue;
678
679 Out << ' ' << Context.print(Block);
680 }
681 });
682}
683
684} // namespace llvm
685
686#undef DEBUG_TYPE
687
688#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:856
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: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
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.
void verifyCycle(CycleRef C) const
Verify that C is actually a well-formed cycle in the CFG.
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 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
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 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ 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)
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:2554
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:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
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:1947
iterator_range< df_iterator< T > > depth_first(const T &G)
#define N
Binary functor that adapts to any other binary functor after dereferencing operands.
Definition STLExtras.h:2342
std::pair< iterator, bool > insert(NodeRef N)