LLVM  15.0.0git
CoroInternal.h
Go to the documentation of this file.
1 //===- CoroInternal.h - Internal Coroutine interfaces ---------*- 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 // Common definitions/declarations used internally by coroutine lowering passes.
9 //===----------------------------------------------------------------------===//
10 
11 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
12 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
13 
14 #include "CoroInstr.h"
15 #include "llvm/IR/IRBuilder.h"
16 
17 namespace llvm {
18 
19 class CallGraph;
20 class CallGraphSCC;
21 class PassRegistry;
22 
23 // CoroEarly pass marks every function that has coro.begin with a string
24 // attribute "coroutine.presplit". CoroSplit pass would processes the
25 // function marked as "coroutine.presplit" only.
26 //
27 // FIXME: Refactor these attributes as LLVM attributes instead of string
28 // attributes since these attributes are already used outside LLVM's
29 // coroutine module.
30 #define CORO_PRESPLIT_ATTR "coroutine.presplit"
31 
32 namespace coro {
33 
34 bool declaresAnyIntrinsic(const Module &M);
35 bool declaresIntrinsics(const Module &M,
36  const std::initializer_list<StringRef>);
37 void replaceCoroFree(CoroIdInst *CoroId, bool Elide);
38 
39 /// Recover a dbg.declare prepared by the frontend and emit an alloca
40 /// holding a pointer to the coroutine frame.
41 void salvageDebugInfo(
43  DbgVariableIntrinsic *DVI, bool OptimizeFrame);
44 
45 // Keeps data and helper functions for lowering coroutine intrinsics.
46 struct LowererBase {
52 
53  LowererBase(Module &M);
54  Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt);
55 };
56 
57 enum class ABI {
58  /// The "resume-switch" lowering, where there are separate resume and
59  /// destroy functions that are shared between all suspend points. The
60  /// coroutine frame implicitly stores the resume and destroy functions,
61  /// the current index, and any promise value.
62  Switch,
63 
64  /// The "returned-continuation" lowering, where each suspend point creates a
65  /// single continuation function that is used for both resuming and
66  /// destroying. Does not support promises.
67  Retcon,
68 
69  /// The "unique returned-continuation" lowering, where each suspend point
70  /// creates a single continuation function that is used for both resuming
71  /// and destroying. Does not support promises. The function is known to
72  /// suspend at most once during its execution, and the return value of
73  /// the continuation is void.
74  RetconOnce,
75 
76  /// The "async continuation" lowering, where each suspend point creates a
77  /// single continuation function. The continuation function is available as an
78  /// intrinsic.
79  Async,
80 };
81 
82 // Holds structural Coroutine Intrinsics for a particular function and other
83 // values used during CoroSplit pass.
91 
92  // Field indexes for special fields in the switch lowering.
94  enum {
96  Destroy
97 
98  // The promise field is always at a fixed offset from the start of
99  // frame given its type, but the index isn't a constant for all
100  // possible frames.
101 
102  // The switch-index field isn't at a fixed offset or index, either;
103  // we just work it in where it fits best.
104  };
105  };
106 
108 
114 
115  /// This would only be true if optimization are enabled.
117 
122  unsigned IndexField;
123  unsigned IndexAlign;
124  unsigned IndexOffset;
126  };
127 
134  };
135 
140  unsigned ContextArgNo;
143  uint64_t FrameOffset; // Start of the frame.
144  uint64_t ContextSize; // Includes frame size.
146 
147  Align getContextAlignment() const { return Align(ContextAlignment); }
148  };
149 
150  union {
154  };
155 
158  return cast<CoroIdInst>(CoroBegin->getId());
159  }
160 
164  return cast<AnyCoroIdRetconInst>(CoroBegin->getId());
165  }
166 
169  return cast<CoroIdAsyncInst>(CoroBegin->getId());
170  }
171 
172  unsigned getSwitchIndexField() const {
174  assert(FrameTy && "frame type not assigned");
175  return SwitchLowering.IndexField;
176  }
179  assert(FrameTy && "frame type not assigned");
180  return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
181  }
183  return ConstantInt::get(getIndexType(), Value);
184  }
185 
188  assert(FrameTy && "frame type not assigned");
189  return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
190  }
191 
193  switch (ABI) {
194  case coro::ABI::Switch:
195  return FunctionType::get(Type::getVoidTy(FrameTy->getContext()),
196  FrameTy->getPointerTo(), /*IsVarArg*/false);
197  case coro::ABI::Retcon:
199  return RetconLowering.ResumePrototype->getFunctionType();
200  case coro::ABI::Async:
201  // Not used. The function type depends on the active suspend.
202  return nullptr;
203  }
204 
205  llvm_unreachable("Unknown coro::ABI enum");
206  }
207 
211  auto FTy = CoroBegin->getFunction()->getFunctionType();
212 
213  // The safety of all this is checked by checkWFRetconPrototype.
214  if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
215  return STy->elements().slice(1);
216  } else {
217  return ArrayRef<Type*>();
218  }
219  }
220 
224 
225  // The safety of all this is checked by checkWFRetconPrototype.
226  auto FTy = RetconLowering.ResumePrototype->getFunctionType();
227  return FTy->params().slice(1);
228  }
229 
231  switch (ABI) {
232  case coro::ABI::Switch:
233  return CallingConv::Fast;
234 
235  case coro::ABI::Retcon:
237  return RetconLowering.ResumePrototype->getCallingConv();
238  case coro::ABI::Async:
239  return AsyncLowering.AsyncCC;
240  }
241  llvm_unreachable("Unknown coro::ABI enum");
242  }
243 
245  if (ABI == coro::ABI::Switch)
246  return SwitchLowering.PromiseAlloca;
247  return nullptr;
248  }
249 
251  if (auto *I = dyn_cast<Instruction>(FramePtr))
252  return I->getNextNode();
253  return &cast<Argument>(FramePtr)->getParent()->getEntryBlock().front();
254  }
255 
256  /// Allocate memory according to the rules of the active lowering.
257  ///
258  /// \param CG - if non-null, will be updated for the new call
259  Value *emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const;
260 
261  /// Deallocate memory according to the rules of the active lowering.
262  ///
263  /// \param CG - if non-null, will be updated for the new call
264  void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const;
265 
266  Shape() = default;
267  explicit Shape(Function &F, bool OptimizeFrame = false)
268  : OptimizeFrame(OptimizeFrame) {
269  buildFrom(F);
270  }
271  void buildFrom(Function &F);
272 };
273 
274 void buildCoroutineFrame(Function &F, Shape &Shape);
275 CallInst *createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
277 } // End namespace coro.
278 } // End namespace llvm
279 
280 #endif
llvm::coro::Shape::CoroSizes
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition: CoroInternal.h:87
llvm::coro::Shape::getInsertPtAfterFramePtr
Instruction * getInsertPtAfterFramePtr() const
Definition: CoroInternal.h:250
llvm::coro::createMustTailCall
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, ArrayRef< Value * > Arguments, IRBuilder<> &)
Definition: CoroSplit.cpp:1629
llvm::coro::Shape::AsyncLoweringStorage::FrameOffset
uint64_t FrameOffset
Definition: CoroInternal.h:143
llvm::coro::Shape::RetconLoweringStorage::ResumePrototype
Function * ResumePrototype
Definition: CoroInternal.h:129
llvm::coro::LowererBase::NullPtr
ConstantPointerNull *const NullPtr
Definition: CoroInternal.h:51
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::coro::Shape::SwitchLowering
SwitchLoweringStorage SwitchLowering
Definition: CoroInternal.h:151
llvm::coro::Shape::FrameTy
StructType * FrameTy
Definition: CoroInternal.h:109
llvm::Function
Definition: Function.h:60
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
llvm::IRBuilder<>
llvm::coro::ABI::Retcon
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
llvm::GlobalVariable
Definition: GlobalVariable.h:39
llvm::coro::LowererBase::Context
LLVMContext & Context
Definition: CoroInternal.h:48
llvm::SmallDenseMap
Definition: DenseMap.h:882
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:361
llvm::coro::Shape::AsyncLoweringStorage::AsyncCC
CallingConv::ID AsyncCC
Definition: CoroInternal.h:139
llvm::CallGraph
The basic data container for the call graph of a Module of IR.
Definition: CallGraph.h:72
llvm::coro::Shape::AsyncLoweringStorage::AsyncFuncTy
FunctionType * AsyncFuncTy
Definition: CoroInternal.h:137
llvm::coro::ABI::Switch
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
llvm::coro::LowererBase::makeSubFnCall
Value * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
Definition: Coroutines.cpp:51
llvm::coro::Shape::ABI
coro::ABI ABI
Definition: CoroInternal.h:107
llvm::CoroBeginInst::getId
AnyCoroIdInst * getId() const
Definition: CoroInstr.h:424
llvm::coro::declaresIntrinsics
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
Definition: Coroutines.cpp:117
llvm::coro::Shape::getPromiseAlloca
AllocaInst * getPromiseAlloca() const
Definition: CoroInternal.h:244
llvm::coro::Shape::SwitchLoweringStorage::ResumeSwitch
SwitchInst * ResumeSwitch
Definition: CoroInternal.h:119
llvm::coro::buildCoroutineFrame
void buildCoroutineFrame(Function &F, Shape &Shape)
Definition: CoroFrame.cpp:2602
llvm::coro::Shape::getAsyncCoroId
CoroIdAsyncInst * getAsyncCoroId() const
Definition: CoroInternal.h:167
llvm::coro::Shape::SwitchLoweringStorage::PromiseAlloca
AllocaInst * PromiseAlloca
Definition: CoroInternal.h:120
llvm::coro::Shape::getResumeFunctionCC
CallingConv::ID getResumeFunctionCC() const
Definition: CoroInternal.h:230
llvm::coro::Shape::AsyncLoweringStorage::ContextHeaderSize
uint64_t ContextHeaderSize
Definition: CoroInternal.h:141
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:186
llvm::ConstantPointerNull
A constant pointer value that points to null.
Definition: Constants.h:534
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::coro::Shape::AllocaSpillBlock
BasicBlock * AllocaSpillBlock
Definition: CoroInternal.h:113
llvm::coro::Shape::RetconLoweringStorage::IsFrameInlineInStorage
bool IsFrameInlineInStorage
Definition: CoroInternal.h:133
llvm::coro::Shape::RetconLoweringStorage
Definition: CoroInternal.h:128
llvm::coro::Shape::getRetconResumeTypes
ArrayRef< Type * > getRetconResumeTypes() const
Definition: CoroInternal.h:221
llvm::coro::Shape::AsyncLoweringStorage::AsyncFuncPointer
GlobalVariable * AsyncFuncPointer
Definition: CoroInternal.h:145
llvm::coro::Shape::getRetconResultTypes
ArrayRef< Type * > getRetconResultTypes() const
Definition: CoroInternal.h:208
llvm::coro::declaresAnyIntrinsic
bool declaresAnyIntrinsic(const Module &M)
Definition: Coroutines.cpp:105
llvm::coro::Shape::CoroSuspends
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition: CoroInternal.h:89
llvm::IntegerType
Class to represent integer types.
Definition: DerivedTypes.h:40
llvm::coro::Shape::SwitchLoweringStorage
Definition: CoroInternal.h:118
llvm::coro::Shape::CoroEnds
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition: CoroInternal.h:86
llvm::coro::Shape::SwitchFieldIndex
Definition: CoroInternal.h:93
llvm::coro::Shape::RetconLoweringStorage::Alloc
Function * Alloc
Definition: CoroInternal.h:130
llvm::coro::replaceCoroFree
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
Definition: Coroutines.cpp:130
llvm::Instruction
Definition: Instruction.h:42
llvm::coro::Shape::SwitchLoweringStorage::HasFinalSuspend
bool HasFinalSuspend
Definition: CoroInternal.h:125
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:919
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::coro::Shape::FrameAlign
Align FrameAlign
Definition: CoroInternal.h:110
llvm::coro::LowererBase::LowererBase
LowererBase(Module &M)
Definition: Coroutines.cpp:38
llvm::coro::Shape::getIndexType
IntegerType * getIndexType() const
Definition: CoroInternal.h:177
llvm::coro::Shape
Definition: CoroInternal.h:84
llvm::coro::Shape::AsyncLowering
AsyncLoweringStorage AsyncLowering
Definition: CoroInternal.h:153
llvm::coro::Shape::AsyncLoweringStorage::ContextAlignment
uint64_t ContextAlignment
Definition: CoroInternal.h:142
llvm::DbgVariableIntrinsic
This is the common base class for debug info intrinsics for variables.
Definition: IntrinsicInst.h:149
llvm::coro::Shape::SwiftErrorOps
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition: CoroInternal.h:90
llvm::CallingConv::Fast
@ Fast
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
llvm::coro::Shape::SwitchFieldIndex::Resume
@ Resume
Definition: CoroInternal.h:95
uint64_t
llvm::coro::Shape::SwitchLoweringStorage::IndexOffset
unsigned IndexOffset
Definition: CoroInternal.h:124
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::coro::Shape::SwitchLoweringStorage::IndexAlign
unsigned IndexAlign
Definition: CoroInternal.h:123
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::CoroIdAsyncInst
This represents the llvm.coro.id.async instruction.
Definition: CoroInstr.h:277
llvm::PointerType
Class to represent pointers.
Definition: DerivedTypes.h:632
llvm::coro::Shape::AsyncLoweringStorage::Context
Value * Context
Definition: CoroInternal.h:138
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::coro::ABI::Async
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
llvm::coro::Shape::OptimizeFrame
bool OptimizeFrame
This would only be true if optimization are enabled.
Definition: CoroInternal.h:116
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
llvm::coro::Shape::AsyncLoweringStorage::ContextSize
uint64_t ContextSize
Definition: CoroInternal.h:144
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:213
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::CoroIdInst
This represents the llvm.coro.id instruction.
Definition: CoroInstr.h:113
llvm::Instruction::getFunction
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:69
llvm::coro::ABI
ABI
Definition: CoroInternal.h:57
LLVM_LIBRARY_VISIBILITY
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library,...
Definition: Compiler.h:125
llvm::coro::Shape::CoroBegin
CoroBeginInst * CoroBegin
Definition: CoroInternal.h:85
llvm::coro::Shape::getResumeFunctionType
FunctionType * getResumeFunctionType() const
Definition: CoroInternal.h:192
llvm::Type::getContext
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
llvm::coro::Shape::SwitchLoweringStorage::ResumeEntryBlock
BasicBlock * ResumeEntryBlock
Definition: CoroInternal.h:121
llvm::coro::Shape::RetconLowering
RetconLoweringStorage RetconLowering
Definition: CoroInternal.h:152
llvm::coro::salvageDebugInfo
void salvageDebugInfo(SmallDenseMap< llvm::Value *, llvm::AllocaInst *, 4 > &DbgPtrAllocaCache, DbgVariableIntrinsic *DVI, bool OptimizeFrame)
Recover a dbg.declare prepared by the frontend and emit an alloca holding a pointer to the coroutine ...
Definition: CoroFrame.cpp:2509
llvm::coro::Shape::CoroAligns
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition: CoroInternal.h:88
llvm::coro::ABI::RetconOnce
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
llvm::coro::Shape::Shape
Shape(Function &F, bool OptimizeFrame=false)
Definition: CoroInternal.h:267
llvm::coro::Shape::getSwitchResumePointerType
PointerType * getSwitchResumePointerType() const
Definition: CoroInternal.h:186
llvm::coro::Shape::getIndex
ConstantInt * getIndex(uint64_t Value) const
Definition: CoroInternal.h:182
llvm::coro::LowererBase::TheModule
Module & TheModule
Definition: CoroInternal.h:47
Arguments
AMDGPU Lower Kernel Arguments
Definition: AMDGPULowerKernelArguments.cpp:243
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:774
llvm::Function::getFunctionType
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:175
llvm::coro::Shape::getSwitchCoroId
CoroIdInst * getSwitchCoroId() const
Definition: CoroInternal.h:156
llvm::coro::Shape::getSwitchIndexField
unsigned getSwitchIndexField() const
Definition: CoroInternal.h:172
llvm::AnyCoroIdRetconInst
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
Definition: CoroInstr.h:204
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:222
llvm::coro::Shape::getRetconCoroId
AnyCoroIdRetconInst * getRetconCoroId() const
Definition: CoroInternal.h:161
llvm::coro::Shape::RetconLoweringStorage::ReturnBlock
BasicBlock * ReturnBlock
Definition: CoroInternal.h:132
llvm::coro::Shape::FrameSize
uint64_t FrameSize
Definition: CoroInternal.h:111
llvm::coro::Shape::AsyncLoweringStorage::ContextArgNo
unsigned ContextArgNo
Definition: CoroInternal.h:140
llvm::coro::LowererBase
Definition: CoroInternal.h:46
llvm::coro::LowererBase::ResumeFnType
FunctionType *const ResumeFnType
Definition: CoroInternal.h:50
llvm::CoroBeginInst
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:420
CoroInstr.h
llvm::StructType::getElementType
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:328
llvm::coro::Shape::FramePtr
Value * FramePtr
Definition: CoroInternal.h:112
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1474
llvm::coro::LowererBase::Int8Ptr
PointerType *const Int8Ptr
Definition: CoroInternal.h:49
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3243
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:58
llvm::coro::Shape::AsyncLoweringStorage::getContextAlignment
Align getContextAlignment() const
Definition: CoroInternal.h:147
llvm::coro::Shape::RetconLoweringStorage::Dealloc
Function * Dealloc
Definition: CoroInternal.h:131
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::coro::Shape::SwitchLoweringStorage::IndexField
unsigned IndexField
Definition: CoroInternal.h:122
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103
llvm::coro::Shape::AsyncLoweringStorage
Definition: CoroInternal.h:136