LLVM 20.0.0git
SuspendCrossingInfo.h
Go to the documentation of this file.
1//===- SuspendCrossingInfo.cpp - Utility for suspend crossing values ------===//
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// The SuspendCrossingInfo maintains data that allows to answer a question
9// whether given two BasicBlocks A and B there is a path from A to B that
10// passes through a suspend point. Note, SuspendCrossingInfo is invalidated
11// by changes to the CFG including adding/removing BBs due to its use of BB
12// ptrs in the BlockToIndexMapping.
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TRANSFORMS_COROUTINES_SUSPENDCROSSINGINFO_H
16#define LLVM_TRANSFORMS_COROUTINES_SUSPENDCROSSINGINFO_H
17
18#include "llvm/ADT/BitVector.h"
21#include "llvm/IR/BasicBlock.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/Instruction.h"
25
26namespace llvm {
27
28class ModuleSlotTracker;
29
30// Provides two way mapping between the blocks and numbers.
33
34public:
35 size_t size() const { return V.size(); }
36
38 for (BasicBlock &BB : F)
39 V.push_back(&BB);
40 llvm::sort(V);
41 }
42
43 size_t blockToIndex(BasicBlock const *BB) const {
44 auto *I = llvm::lower_bound(V, BB);
45 assert(I != V.end() && *I == BB && "BasicBlockNumberng: Unknown block");
46 return I - V.begin();
47 }
48
49 BasicBlock *indexToBlock(unsigned Index) const { return V[Index]; }
50};
51
52// The SuspendCrossingInfo maintains data that allows to answer a question
53// whether given two BasicBlocks A and B there is a path from A to B that
54// passes through a suspend point.
55//
56// For every basic block 'i' it maintains a BlockData that consists of:
57// Consumes: a bit vector which contains a set of indices of blocks that can
58// reach block 'i'. A block can trivially reach itself.
59// Kills: a bit vector which contains a set of indices of blocks that can
60// reach block 'i' but there is a path crossing a suspend point
61// not repeating 'i' (path to 'i' without cycles containing 'i').
62// Suspend: a boolean indicating whether block 'i' contains a suspend point.
63// End: a boolean indicating whether block 'i' contains a coro.end intrinsic.
64// KillLoop: There is a path from 'i' to 'i' not otherwise repeating 'i' that
65// crosses a suspend point.
66//
68 BlockToIndexMapping Mapping;
69
70 struct BlockData {
71 BitVector Consumes;
72 BitVector Kills;
73 bool Suspend = false;
74 bool End = false;
75 bool KillLoop = false;
76 bool Changed = false;
77 };
79
80 iterator_range<pred_iterator> predecessors(BlockData const &BD) const {
81 BasicBlock *BB = Mapping.indexToBlock(&BD - &Block[0]);
82 return llvm::predecessors(BB);
83 }
84
85 BlockData &getBlockData(BasicBlock *BB) {
86 return Block[Mapping.blockToIndex(BB)];
87 }
88
89 /// Compute the BlockData for the current function in one iteration.
90 /// Initialize - Whether this is the first iteration, we can optimize
91 /// the initial case a little bit by manual loop switch.
92 /// Returns whether the BlockData changes in this iteration.
93 template <bool Initialize = false>
94 bool computeBlockData(const ReversePostOrderTraversal<Function *> &RPOT);
95
96public:
97#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
98 // Print order is in RPO
99 void dump() const;
100 void dump(StringRef Label, BitVector const &BV,
102 ModuleSlotTracker &MST) const;
103#endif
104
106 const SmallVectorImpl<AnyCoroSuspendInst *> &CoroSuspends,
107 const SmallVectorImpl<AnyCoroEndInst *> &CoroEnds);
108
109 /// Returns true if there is a path from \p From to \p To crossing a suspend
110 /// point without crossing \p From a 2nd time.
112
113 /// Returns true if there is a path from \p From to \p To crossing a suspend
114 /// point without crossing \p From a 2nd time. If \p From is the same as \p To
115 /// this will also check if there is a looping path crossing a suspend point.
117 BasicBlock *To) const;
118
120 auto *I = cast<Instruction>(U);
121
122 // We rewrote PHINodes, so that only the ones with exactly one incoming
123 // value need to be analyzed.
124 if (auto *PN = dyn_cast<PHINode>(I))
125 if (PN->getNumIncomingValues() > 1)
126 return false;
127
128 BasicBlock *UseBB = I->getParent();
129
130 // As a special case, treat uses by an llvm.coro.suspend.retcon or an
131 // llvm.coro.suspend.async as if they were uses in the suspend's single
132 // predecessor: the uses conceptually occur before the suspend.
133 if (isa<CoroSuspendRetconInst>(I) || isa<CoroSuspendAsyncInst>(I)) {
134 UseBB = UseBB->getSinglePredecessor();
135 assert(UseBB && "should have split coro.suspend into its own block");
136 }
137
138 return hasPathCrossingSuspendPoint(DefBB, UseBB);
139 }
140
142 return isDefinitionAcrossSuspend(&A.getParent()->getEntryBlock(), U);
143 }
144
146 auto *DefBB = I.getParent();
147
148 // As a special case, treat values produced by an llvm.coro.suspend.*
149 // as if they were defined in the single successor: the uses
150 // conceptually occur after the suspend.
151 if (isa<AnyCoroSuspendInst>(I)) {
152 DefBB = DefBB->getSingleSuccessor();
153 assert(DefBB && "should have split coro.suspend into its own block");
154 }
155
156 return isDefinitionAcrossSuspend(DefBB, U);
157 }
158
160 if (auto *Arg = dyn_cast<Argument>(&V))
161 return isDefinitionAcrossSuspend(*Arg, U);
162 if (auto *Inst = dyn_cast<Instruction>(&V))
163 return isDefinitionAcrossSuspend(*Inst, U);
164
166 "Coroutine could only collect Argument and Instruction now.");
167 }
168
170 if (auto *Arg = dyn_cast<Argument>(&V)) {
171 for (User *U : Arg->users())
172 if (isDefinitionAcrossSuspend(*Arg, U))
173 return true;
174 } else if (auto *Inst = dyn_cast<Instruction>(&V)) {
175 for (User *U : Inst->users())
176 if (isDefinitionAcrossSuspend(*Inst, U))
177 return true;
178 }
179
181 "Coroutine could only collect Argument and Instruction now.");
182 }
183};
184
185} // namespace llvm
186
187#endif // LLVM_TRANSFORMS_COROUTINES_SUSPENDCROSSINGINFO_H
This file implements the BitVector class.
BlockVerifier::State From
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
uint32_t Index
bool End
Definition: ELF_riscv.cpp:480
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
Definition: BasicBlock.cpp:459
size_t blockToIndex(BasicBlock const *BB) const
BasicBlock * indexToBlock(unsigned Index) const
Manage lifetime of a slot tracker for printing IR.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
bool isDefinitionAcrossSuspend(Value &V) const
bool isDefinitionAcrossSuspend(Value &V, User *U) const
bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const
bool hasPathCrossingSuspendPoint(BasicBlock *From, BasicBlock *To) const
Returns true if there is a path from From to To crossing a suspend point without crossing From a 2nd ...
bool isDefinitionAcrossSuspend(Instruction &I, User *U) const
bool hasPathOrLoopCrossingSuspendPoint(BasicBlock *From, BasicBlock *To) const
Returns true if there is a path from From to To crossing a suspend point without crossing From a 2nd ...
bool isDefinitionAcrossSuspend(Argument &A, User *U) const
LLVM Value Representation.
Definition: Value.h:74
A range adaptor for a pair of iterators.
#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.
Definition: AddressRanges.h:18
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1978
auto predecessors(const MachineBasicBlock *BB)