LLVM 20.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
31#define DEBUG_TYPE "generic-cycle-impl"
32
33namespace llvm {
34
35template <typename ContextT>
37 if (!C)
38 return false;
39
40 if (Depth > C->Depth)
41 return false;
42 while (Depth < C->Depth)
43 C = C->ParentCycle;
44 return this == C;
45}
46
47template <typename ContextT>
49 SmallVectorImpl<BlockT *> &TmpStorage) const {
50 TmpStorage.clear();
51
52 size_t NumExitBlocks = 0;
53 for (BlockT *Block : blocks()) {
55
56 for (size_t Idx = NumExitBlocks, End = TmpStorage.size(); Idx < End;
57 ++Idx) {
58 BlockT *Succ = TmpStorage[Idx];
59 if (!contains(Succ)) {
60 auto ExitEndIt = TmpStorage.begin() + NumExitBlocks;
61 if (std::find(TmpStorage.begin(), ExitEndIt, Succ) == ExitEndIt)
62 TmpStorage[NumExitBlocks++] = Succ;
63 }
64 }
65
66 TmpStorage.resize(NumExitBlocks);
67 }
68}
69
70template <typename ContextT>
72 SmallVectorImpl<BlockT *> &TmpStorage) const {
73 TmpStorage.clear();
74
75 for (BlockT *Block : blocks()) {
76 for (BlockT *Succ : successors(Block)) {
77 if (!contains(Succ)) {
78 TmpStorage.push_back(Block);
79 break;
80 }
81 }
82 }
83}
84
85template <typename ContextT>
87 BlockT *Predecessor = getCyclePredecessor();
88 if (!Predecessor)
89 return nullptr;
90
91 assert(isReducible() && "Cycle Predecessor must be in a reducible cycle!");
92
93 if (succ_size(Predecessor) != 1)
94 return nullptr;
95
96 // Make sure we are allowed to hoist instructions into the predecessor.
97 if (!Predecessor->isLegalToHoistInto())
98 return nullptr;
99
100 return Predecessor;
101}
102
103template <typename ContextT>
105 if (!isReducible())
106 return nullptr;
107
108 BlockT *Out = nullptr;
109
110 // Loop over the predecessors of the header node...
111 BlockT *Header = getHeader();
112 for (const auto Pred : predecessors(Header)) {
113 if (!contains(Pred)) {
114 if (Out && Out != Pred)
115 return nullptr;
116 Out = Pred;
117 }
118 }
119
120 return Out;
121}
122
123/// \brief Verify that this is actually a well-formed cycle in the CFG.
124template <typename ContextT> void GenericCycle<ContextT>::verifyCycle() const {
125#ifndef NDEBUG
126 assert(!Blocks.empty() && "Cycle cannot be empty.");
128 for (BlockT *BB : blocks()) {
129 assert(Blocks.insert(BB).second); // duplicates in block list?
130 }
131 assert(!Entries.empty() && "Cycle must have one or more entries.");
132
133 DenseSet<BlockT *> Entries;
134 for (BlockT *Entry : entries()) {
135 assert(Entries.insert(Entry).second); // duplicate entry?
136 assert(contains(Entry));
137 }
138
139 // Setup for using a depth-first iterator to visit every block in the cycle.
141 getExitBlocks(ExitBBs);
143 VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
144
145 // Keep track of the BBs visited.
146 SmallPtrSet<BlockT *, 8> VisitedBBs;
147
148 // Check the individual blocks.
149 for (BlockT *BB : depth_first_ext(getHeader(), VisitSet)) {
150 assert(llvm::any_of(llvm::children<BlockT *>(BB),
151 [&](BlockT *B) { return contains(B); }) &&
152 "Cycle block has no in-cycle successors!");
153
154 assert(llvm::any_of(llvm::inverse_children<BlockT *>(BB),
155 [&](BlockT *B) { return contains(B); }) &&
156 "Cycle block has no in-cycle predecessors!");
157
158 DenseSet<BlockT *> OutsideCyclePreds;
159 for (BlockT *B : llvm::inverse_children<BlockT *>(BB))
160 if (!contains(B))
161 OutsideCyclePreds.insert(B);
162
163 if (Entries.contains(BB)) {
164 assert(!OutsideCyclePreds.empty() && "Entry is unreachable!");
165 } else if (!OutsideCyclePreds.empty()) {
166 // A non-entry block shouldn't be reachable from outside the cycle,
167 // though it is permitted if the predecessor is not itself actually
168 // reachable.
169 BlockT *EntryBB = &BB->getParent()->front();
170 for (BlockT *CB : depth_first(EntryBB))
171 assert(!OutsideCyclePreds.contains(CB) &&
172 "Non-entry block reachable from outside!");
173 }
174 assert(BB != &getHeader()->getParent()->front() &&
175 "Cycle contains function entry block!");
176
177 VisitedBBs.insert(BB);
178 }
179
180 if (VisitedBBs.size() != getNumBlocks()) {
181 dbgs() << "The following blocks are unreachable in the cycle:\n ";
182 ListSeparator LS;
183 for (auto *BB : Blocks) {
184 if (!VisitedBBs.count(BB)) {
185 dbgs() << LS;
186 BB->printAsOperand(dbgs());
187 }
188 }
189 dbgs() << "\n";
190 llvm_unreachable("Unreachable block in cycle");
191 }
192
193 verifyCycleNest();
194#endif
195}
196
197/// \brief Verify the parent-child relations of this cycle.
198///
199/// Note that this does \em not check that cycle is really a cycle in the CFG.
200template <typename ContextT>
202#ifndef NDEBUG
203 // Check the subcycles.
204 for (GenericCycle *Child : children()) {
205 // Each block in each subcycle should be contained within this cycle.
206 for (BlockT *BB : Child->blocks()) {
207 assert(contains(BB) &&
208 "Cycle does not contain all the blocks of a subcycle!");
209 }
210 assert(Child->Depth == Depth + 1);
211 }
212
213 // Check the parent cycle pointer.
214 if (ParentCycle) {
215 assert(is_contained(ParentCycle->children(), this) &&
216 "Cycle is not a subcycle of its parent!");
217 }
218#endif
219}
220
221/// \brief Helper class for computing cycle information.
222template <typename ContextT> class GenericCycleInfoCompute {
223 using BlockT = typename ContextT::BlockT;
224 using CycleInfoT = GenericCycleInfo<ContextT>;
225 using CycleT = typename CycleInfoT::CycleT;
226
227 CycleInfoT &Info;
228
229 struct DFSInfo {
230 unsigned Start = 0; // DFS start; positive if block is found
231 unsigned End = 0; // DFS end
232
233 DFSInfo() = default;
234 explicit DFSInfo(unsigned Start) : Start(Start) {}
235
236 explicit operator bool() const { return Start; }
237
238 /// Whether this node is an ancestor (or equal to) the node \p Other
239 /// in the DFS tree.
240 bool isAncestorOf(const DFSInfo &Other) const {
241 return Start <= Other.Start && Other.End <= End;
242 }
243 };
244
245 DenseMap<BlockT *, DFSInfo> BlockDFSInfo;
246 SmallVector<BlockT *, 8> BlockPreorder;
247
249 GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
250
251public:
252 GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
253
254 void run(BlockT *EntryBlock);
255
256 static void updateDepth(CycleT *SubTree);
257
258private:
259 void dfs(BlockT *EntryBlock);
260};
261
262template <typename ContextT>
264 -> CycleT * {
265 auto Cycle = BlockMapTopLevel.find(Block);
266 if (Cycle != BlockMapTopLevel.end())
267 return Cycle->second;
268
269 auto MapIt = BlockMap.find(Block);
270 if (MapIt == BlockMap.end())
271 return nullptr;
272
273 auto *C = MapIt->second;
274 while (C->ParentCycle)
275 C = C->ParentCycle;
276 BlockMapTopLevel.try_emplace(Block, C);
277 return C;
280template <typename ContextT>
282 CycleT *Child) {
283 assert((!Child->ParentCycle && !NewParent->ParentCycle) &&
284 "NewParent and Child must be both top level cycle!\n");
285 auto &CurrentContainer =
286 Child->ParentCycle ? Child->ParentCycle->Children : TopLevelCycles;
287 auto Pos = llvm::find_if(CurrentContainer, [=](const auto &Ptr) -> bool {
288 return Child == Ptr.get();
289 });
290 assert(Pos != CurrentContainer.end());
291 NewParent->Children.push_back(std::move(*Pos));
292 *Pos = std::move(CurrentContainer.back());
293 CurrentContainer.pop_back();
294 Child->ParentCycle = NewParent;
295
296 NewParent->Blocks.insert(Child->block_begin(), Child->block_end());
297
298 for (auto &It : BlockMapTopLevel)
299 if (It.second == Child)
300 It.second = NewParent;
301}
302
303template <typename ContextT>
304void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
305 // FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
306 // printing, cycle NewBlock is at the end of list but it should be in the
307 // middle to represent actual traversal of a cycle.
308 Cycle->appendBlock(Block);
309 BlockMap.try_emplace(Block, Cycle);
310
311 CycleT *ParentCycle = Cycle->getParentCycle();
312 while (ParentCycle) {
313 Cycle = ParentCycle;
314 Cycle->appendBlock(Block);
315 ParentCycle = Cycle->getParentCycle();
316 }
317
318 BlockMapTopLevel.try_emplace(Block, Cycle);
319}
320
321/// \brief Main function of the cycle info computations.
322template <typename ContextT>
324 LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock)
325 << "\n");
326 dfs(EntryBlock);
327
329
330 for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) {
331 const DFSInfo CandidateInfo = BlockDFSInfo.lookup(HeaderCandidate);
332
333 for (BlockT *Pred : predecessors(HeaderCandidate)) {
334 const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
335 // This automatically ignores unreachable predecessors since they have
336 // zeros in their DFSInfo.
337 if (CandidateInfo.isAncestorOf(PredDFSInfo))
338 Worklist.push_back(Pred);
339 }
340 if (Worklist.empty()) {
341 continue;
342 }
343
344 // Found a cycle with the candidate as its header.
345 LLVM_DEBUG(errs() << "Found cycle for header: "
346 << Info.Context.print(HeaderCandidate) << "\n");
347 std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>();
348 NewCycle->appendEntry(HeaderCandidate);
349 NewCycle->appendBlock(HeaderCandidate);
350 Info.BlockMap.try_emplace(HeaderCandidate, NewCycle.get());
351
352 // Helper function to process (non-back-edge) predecessors of a discovered
353 // block and either add them to the worklist or recognize that the given
354 // block is an additional cycle entry.
355 auto ProcessPredecessors = [&](BlockT *Block) {
356 LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": ");
357
358 bool IsEntry = false;
359 for (BlockT *Pred : predecessors(Block)) {
360 const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
361 if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
362 Worklist.push_back(Pred);
363 } else if (!PredDFSInfo) {
364 // Ignore an unreachable predecessor. It will will incorrectly cause
365 // Block to be treated as a cycle entry.
366 LLVM_DEBUG(errs() << " skipped unreachable predecessor.\n");
367 } else {
368 IsEntry = true;
369 }
370 }
371 if (IsEntry) {
372 assert(!NewCycle->isEntry(Block));
373 LLVM_DEBUG(errs() << "append as entry\n");
374 NewCycle->appendEntry(Block);
375 } else {
376 LLVM_DEBUG(errs() << "append as child\n");
377 }
378 };
379
380 do {
381 BlockT *Block = Worklist.pop_back_val();
382 if (Block == HeaderCandidate)
383 continue;
384
385 // If the block has already been discovered by some cycle
386 // (possibly by ourself), then the outermost cycle containing it
387 // should become our child.
388 if (auto *BlockParent = Info.getTopLevelParentCycle(Block)) {
389 LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": ");
390
391 if (BlockParent != NewCycle.get()) {
393 << "discovered child cycle "
394 << Info.Context.print(BlockParent->getHeader()) << "\n");
395 // Make BlockParent the child of NewCycle.
396 Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent);
397
398 for (auto *ChildEntry : BlockParent->entries())
399 ProcessPredecessors(ChildEntry);
400 } else {
402 << "known child cycle "
403 << Info.Context.print(BlockParent->getHeader()) << "\n");
404 }
405 } else {
406 Info.BlockMap.try_emplace(Block, NewCycle.get());
407 assert(!is_contained(NewCycle->Blocks, Block));
408 NewCycle->Blocks.insert(Block);
409 ProcessPredecessors(Block);
410 Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get());
411 }
412 } while (!Worklist.empty());
413
414 Info.TopLevelCycles.push_back(std::move(NewCycle));
415 }
416
417 // Fix top-level cycle links and compute cycle depths.
418 for (auto *TLC : Info.toplevel_cycles()) {
419 LLVM_DEBUG(errs() << "top-level cycle: "
420 << Info.Context.print(TLC->getHeader()) << "\n");
421
422 TLC->ParentCycle = nullptr;
423 updateDepth(TLC);
424 }
425}
426
427/// \brief Recompute depth values of \p SubTree and all descendants.
428template <typename ContextT>
430 for (CycleT *Cycle : depth_first(SubTree))
431 Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1;
432}
433
434/// \brief Compute a DFS of basic blocks starting at the function entry.
435///
436/// Fills BlockDFSInfo with start/end counters and BlockPreorder.
437template <typename ContextT>
438void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
439 SmallVector<unsigned, 8> DFSTreeStack;
440 SmallVector<BlockT *, 8> TraverseStack;
441 unsigned Counter = 0;
442 TraverseStack.emplace_back(EntryBlock);
443
444 do {
445 BlockT *Block = TraverseStack.back();
446 LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block)
447 << "\n");
448 if (!BlockDFSInfo.count(Block)) {
449 // We're visiting the block for the first time. Open its DFSInfo, add
450 // successors to the traversal stack, and remember the traversal stack
451 // depth at which the block was opened, so that we can correctly record
452 // its end time.
453 LLVM_DEBUG(errs() << " first encountered at depth "
454 << TraverseStack.size() << "\n");
455
456 DFSTreeStack.emplace_back(TraverseStack.size());
457 llvm::append_range(TraverseStack, successors(Block));
458
459 bool Added = BlockDFSInfo.try_emplace(Block, ++Counter).second;
460 (void)Added;
461 assert(Added);
462 BlockPreorder.push_back(Block);
463 LLVM_DEBUG(errs() << " preorder number: " << Counter << "\n");
464 } else {
465 assert(!DFSTreeStack.empty());
466 if (DFSTreeStack.back() == TraverseStack.size()) {
467 LLVM_DEBUG(errs() << " ended at " << Counter << "\n");
468 BlockDFSInfo.find(Block)->second.End = Counter;
469 DFSTreeStack.pop_back();
470 } else {
471 LLVM_DEBUG(errs() << " already done\n");
472 }
473 TraverseStack.pop_back();
474 }
475 } while (!TraverseStack.empty());
476 assert(DFSTreeStack.empty());
477
479 errs() << "Preorder:\n";
480 for (int i = 0, e = BlockPreorder.size(); i != e; ++i) {
481 errs() << " " << Info.Context.print(BlockPreorder[i]) << ": " << i << "\n";
482 }
483 );
484}
485
486/// \brief Reset the object to its initial state.
487template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
488 TopLevelCycles.clear();
489 BlockMap.clear();
490 BlockMapTopLevel.clear();
491}
492
493/// \brief Compute the cycle info for a function.
494template <typename ContextT>
497 Context = ContextT(&F);
498
499 LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
500 << "\n");
501 Compute.run(&F.front());
502}
503
504template <typename ContextT>
506 BlockT *NewBlock) {
507 // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
508 // cycles that had blocks Pred and Succ also get NewBlock.
509 CycleT *Cycle = getSmallestCommonCycle(getCycle(Pred), getCycle(Succ));
510 if (!Cycle)
511 return;
512
513 addBlockToCycle(NewBlock, Cycle);
514 verifyCycleNest();
515}
516
517/// \brief Find the innermost cycle containing a given block.
518///
519/// \returns the innermost cycle containing \p Block or nullptr if
520/// it is not contained in any cycle.
521template <typename ContextT>
523 -> CycleT * {
524 return BlockMap.lookup(Block);
525}
526
527/// \brief Find the innermost cycle containing both given cycles.
528///
529/// \returns the innermost cycle containing both \p A and \p B
530/// or nullptr if there is no such cycle.
531template <typename ContextT>
533 CycleT *B) const
534 -> CycleT * {
535 if (!A || !B)
536 return nullptr;
537
538 // If cycles A and B have different depth replace them with parent cycle
539 // until they have the same depth.
540 while (A->getDepth() > B->getDepth())
541 A = A->getParentCycle();
542 while (B->getDepth() > A->getDepth())
543 B = B->getParentCycle();
544
545 // Cycles A and B are at same depth but may be disjoint, replace them with
546 // parent cycles until we find cycle that contains both or we run out of
547 // parent cycles.
548 while (A != B) {
549 A = A->getParentCycle();
550 B = B->getParentCycle();
551 }
552
553 return A;
554}
555
556/// \brief get the depth for the cycle which containing a given block.
557///
558/// \returns the depth for the innermost cycle containing \p Block or 0 if it is
559/// not contained in any cycle.
560template <typename ContextT>
562 CycleT *Cycle = getCycle(Block);
563 if (!Cycle)
564 return 0;
565 return Cycle->getDepth();
566}
567
568/// \brief Verify the internal consistency of the cycle tree.
569///
570/// Note that this does \em not check that cycles are really cycles in the CFG,
571/// or that the right set of cycles in the CFG were found.
572template <typename ContextT>
574#ifndef NDEBUG
575 DenseSet<BlockT *> CycleHeaders;
576
577 for (CycleT *TopCycle : toplevel_cycles()) {
578 for (CycleT *Cycle : depth_first(TopCycle)) {
579 BlockT *Header = Cycle->getHeader();
580 assert(CycleHeaders.insert(Header).second);
581 if (VerifyFull)
583 else
585 // Check the block map entries for blocks contained in this cycle.
586 for (BlockT *BB : Cycle->blocks()) {
587 auto MapIt = BlockMap.find(BB);
588 assert(MapIt != BlockMap.end());
589 assert(Cycle->contains(MapIt->second));
590 }
591 }
592 }
593#endif
594}
595
596/// \brief Verify that the entire cycle tree well-formed.
597template <typename ContextT> void GenericCycleInfo<ContextT>::verify() const {
598 verifyCycleNest(/*VerifyFull=*/true);
599}
600
601/// \brief Print the cycle info.
602template <typename ContextT>
604 for (const auto *TLC : toplevel_cycles()) {
605 for (const CycleT *Cycle : depth_first(TLC)) {
606 for (unsigned I = 0; I < Cycle->Depth; ++I)
607 Out << " ";
608
609 Out << Cycle->print(Context) << '\n';
610 }
611 }
612}
613
614} // namespace llvm
615
616#undef DEBUG_TYPE
617
618#endif // LLVM_ADT_GENERICCYCLEIMPL_H
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
bool End
Definition: ELF_riscv.cpp:480
DenseMap< Block *, BlockRelaxAux > Blocks
Definition: ELF_riscv.cpp:507
Find all cycles in a control-flow graph, including irreducible loops.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some functions that are useful when dealing with strings.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Helper class for computing cycle information.
void run(BlockT *EntryBlock)
Main function of the cycle info computations.
GenericCycleInfoCompute(CycleInfoT &Info)
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 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.
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 * getTopLevelParentCycle(BlockT *Block)
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
A possibly irreducible generalization of a Loop.
BlockT * getHeader() const
void getExitingBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of this cycle that have successor outside of this cycle.
void verifyCycle() const
Verify that this is actually a well-formed cycle in the CFG.
void verifyCycleNest() const
Verify the parent-child relations of this cycle.
Printable print(const ContextT &Ctx) const
iterator_range< const_block_iterator > blocks() const
BlockT * getCyclePreheader() const
Return the preheader block for this cycle.
const_block_iterator block_begin() const
void getExitBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all of the successor blocks of this cycle.
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.
typename ContextT::BlockT BlockT
const GenericCycle * getParentCycle() const
unsigned getDepth() const
const_block_iterator block_end() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
size_type size() const
Definition: SmallPtrSet.h:95
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:435
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:367
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:502
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
void resize(size_type N)
Definition: SmallVector.h:651
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:185
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#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.
Definition: AddressRanges.h:18
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:2098
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:1729
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:419
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Other
Any other memory.
CycleInfo::CycleT Cycle
Definition: CycleInfo.h:24
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:1749
auto predecessors(const MachineBasicBlock *BB)
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
Definition: GraphTraits.h:149
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1886
iterator_range< df_iterator< T > > depth_first(const T &G)
unsigned succ_size(const MachineBasicBlock *BB)
std::pair< iterator, bool > insert(NodeRef N)