LLVM 24.0.0git
CoroShape.h
Go to the documentation of this file.
1//===- CoroShape.h - Coroutine info for lowering --------------*- 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// This file declares the shape info struct that is required by many coroutine
9// utility methods.
10//===----------------------------------------------------------------------===//
11
12#ifndef LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
13#define LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
14
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/PassManager.h"
20
21namespace llvm {
22
23class CallGraph;
24
25namespace coro {
26
27enum class ABI {
28 /// The "resume-switch" lowering, where there are separate resume and
29 /// destroy functions that are shared between all suspend points. The
30 /// coroutine frame implicitly stores the resume and destroy functions,
31 /// the current index, and any promise value.
33
34 /// The "returned-continuation" lowering, where each suspend point creates a
35 /// single continuation function that is used for both resuming and
36 /// destroying. Does not support promises.
38
39 /// The "unique returned-continuation" lowering, where each suspend point
40 /// creates a single continuation function that is used for both resuming
41 /// and destroying. Does not support promises. The function is known to
42 /// suspend at most once during its execution, and the return value of
43 /// the continuation is void.
45
46 /// The "async continuation" lowering, where each suspend point creates a
47 /// single continuation function. The continuation function is available as an
48 /// intrinsic.
50};
51
52// Holds structural Coroutine Intrinsics for a particular function and other
53// values used during CoroSplit pass.
54struct Shape {
61 // Map from suspend instructions to their execution frequency, used for branch
62 // weights in the resume function.
64 // Estimated profile execution count for the resume function if available.
65 std::optional<uint64_t> ResumeEntryCount;
68
69 // Values invalidated by replaceSwiftErrorOps()
71
72 void clear() {
73 CoroBegin = nullptr;
74 CoroEnds.clear();
75 CoroIsInRampInsts.clear();
76 CoroSizes.clear();
77 CoroAligns.clear();
78 CoroSuspends.clear();
79 SuspendFreqs.clear();
80 ResumeEntryCount = std::nullopt;
81 CoroAwaitSuspends.clear();
82 SymmetricTransfers.clear();
83
84 SwiftErrorOps.clear();
85
86 FramePtr = nullptr;
87 AllocaSpillBlock = nullptr;
88 }
89
90 // Scan the function and collect the above intrinsics for later processing
93 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
94 // If for some reason, we were not able to find coro.begin, bailout.
95 LLVM_ABI void
98 // Remove orphaned and unnecessary intrinsics
99 LLVM_ABI void
101 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
102
104
107 Value *FramePtr = nullptr;
109
123
131
144
145 union {
149 };
150
153 return cast<CoroIdInst>(CoroBegin->getId());
154 }
155
160
165
168 assert(SwitchLowering.IndexType && "index type not assigned");
169 return SwitchLowering.IndexType;
170 }
172 return ConstantInt::get(getIndexType(), Value);
173 }
174
177 assert(CoroBegin && "CoroBegin not assigned");
178 return PointerType::getUnqual(CoroBegin->getContext());
179 }
180
182 switch (ABI) {
184 return FunctionType::get(Type::getVoidTy(CoroBegin->getContext()),
185 PointerType::getUnqual(CoroBegin->getContext()),
186 /*IsVarArg=*/false);
189 return RetconLowering.ResumePrototype->getFunctionType();
190 case coro::ABI::Async:
191 // Not used. The function type depends on the active suspend.
192 return nullptr;
193 }
194
195 llvm_unreachable("Unknown coro::ABI enum");
196 }
197
200 auto FTy = CoroBegin->getFunction()->getFunctionType();
201
202 // The safety of all this is checked by checkWFRetconPrototype.
203 if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
204 return STy->elements().slice(1);
205 } else {
206 return ArrayRef<Type *>();
207 }
208 }
209
212
213 // The safety of all this is checked by checkWFRetconPrototype.
214 auto FTy = RetconLowering.ResumePrototype->getFunctionType();
215 return FTy->params().slice(1);
216 }
217
219 switch (ABI) {
221 // Use the platform C calling convention so that resume/destroy
222 // function pointers stored in the coroutine frame are
223 // interoperable with other compilers.
224 return CallingConv::C;
225
228 return RetconLowering.ResumePrototype->getCallingConv();
229 case coro::ABI::Async:
230 return AsyncLowering.AsyncCC;
231 }
232 llvm_unreachable("Unknown coro::ABI enum");
233 }
234
236 if (ABI == coro::ABI::Switch)
237 return SwitchLowering.PromiseAlloca;
238 return nullptr;
239 }
240
242 if (auto *I = dyn_cast<Instruction>(FramePtr)) {
243 BasicBlock::iterator It = std::next(I->getIterator());
244 It.setHeadBit(true); // Copy pre-RemoveDIs behaviour.
245 return It;
246 }
247 return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin();
248 }
249
250 /// Allocate memory according to the rules of the active lowering.
251 ///
252 /// \param CG - if non-null, will be updated for the new call
254 CallGraph *CG) const;
255
256 /// Deallocate memory according to the rules of the active lowering.
257 ///
258 /// \param CG - if non-null, will be updated for the new call
259 LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr,
260 CallGraph *CG) const;
261
262 Shape() = default;
263 explicit Shape(Function &F) {
265 SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
266
267 analyze(F, CoroFrames, UnusedCoroSaves);
268 if (!CoroBegin) {
269 invalidateCoroutine(F, CoroFrames);
270 return;
271 }
272 cleanCoroutine(CoroFrames, UnusedCoroSaves);
273 }
274};
275
276} // end namespace coro
277
278} // end namespace llvm
279
280#endif // LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
#define LLVM_ABI
Definition Compiler.h:215
This file defines the DenseMap class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
an instruction to allocate memory on the stack
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
Definition CoroInstr.h:238
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM Basic Block Representation.
Definition BasicBlock.h:62
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
The basic data container for the call graph of a Module of IR.
Definition CallGraph.h:72
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Definition CoroInstr.h:479
This represents the llvm.coro.id.async instruction.
Definition CoroInstr.h:310
This represents the llvm.coro.id instruction.
Definition CoroInstr.h:148
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
Class to represent integer types.
Class to represent pointers.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Multiway switch.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
LLVM Value Representation.
Definition Value.h:75
#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
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
Definition CoroShape.h:49
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
Definition CoroShape.h:44
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
Definition CoroShape.h:37
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
Definition CoroShape.h:32
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
SmallVector< CallInst *, 2 > SymmetricTransfers
Definition CoroShape.h:67
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
Definition CoroShape.h:66
AsyncLoweringStorage AsyncLowering
Definition CoroShape.h:148
FunctionType * getResumeFunctionType() const
Definition CoroShape.h:181
IntegerType * getIndexType() const
Definition CoroShape.h:166
AnyCoroIdRetconInst * getRetconCoroId() const
Definition CoroShape.h:156
PointerType * getSwitchResumePointerType() const
Definition CoroShape.h:175
CoroIdInst * getSwitchCoroId() const
Definition CoroShape.h:151
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition CoroShape.h:58
CallingConv::ID getResumeFunctionCC() const
Definition CoroShape.h:218
Shape(Function &F)
Definition CoroShape.h:263
ArrayRef< Type * > getRetconResumeTypes() const
Definition CoroShape.h:210
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition CoroShape.h:60
uint64_t FrameSize
Definition CoroShape.h:106
LLVM_ABI Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
std::optional< uint64_t > ResumeEntryCount
Definition CoroShape.h:65
LLVM_ABI void cleanCoroutine(SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves)
ConstantInt * getIndex(uint64_t Value) const
Definition CoroShape.h:171
AllocaInst * getPromiseAlloca() const
Definition CoroShape.h:235
SwitchLoweringStorage SwitchLowering
Definition CoroShape.h:146
CoroBeginInst * CoroBegin
Definition CoroShape.h:55
SmallDenseMap< AnyCoroSuspendInst *, uint64_t, 4 > SuspendFreqs
Definition CoroShape.h:63
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition CoroShape.h:241
ArrayRef< Type * > getRetconResultTypes() const
Definition CoroShape.h:198
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
Definition CoroShape.h:57
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
Definition CoroShape.h:147
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition CoroShape.h:59
CoroIdAsyncInst * getAsyncCoroId() const
Definition CoroShape.h:161
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition CoroShape.h:56
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition CoroShape.h:70
LLVM_ABI void invalidateCoroutine(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames)
BasicBlock * AllocaSpillBlock
Definition CoroShape.h:108
LLVM_ABI void analyze(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves)