LLVM  16.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 
21 namespace coro {
22 
23 bool declaresAnyIntrinsic(const Module &M);
24 bool declaresIntrinsics(const Module &M,
25  const std::initializer_list<StringRef>);
26 void replaceCoroFree(CoroIdInst *CoroId, bool Elide);
27 
28 /// Recover a dbg.declare prepared by the frontend and emit an alloca
29 /// holding a pointer to the coroutine frame.
30 void salvageDebugInfo(
32  DbgVariableIntrinsic *DVI, bool OptimizeFrame);
33 
34 // Keeps data and helper functions for lowering coroutine intrinsics.
35 struct LowererBase {
41 
42  LowererBase(Module &M);
43  Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt);
44 };
45 
46 enum class ABI {
47  /// The "resume-switch" lowering, where there are separate resume and
48  /// destroy functions that are shared between all suspend points. The
49  /// coroutine frame implicitly stores the resume and destroy functions,
50  /// the current index, and any promise value.
51  Switch,
52 
53  /// The "returned-continuation" lowering, where each suspend point creates a
54  /// single continuation function that is used for both resuming and
55  /// destroying. Does not support promises.
56  Retcon,
57 
58  /// The "unique returned-continuation" lowering, where each suspend point
59  /// creates a single continuation function that is used for both resuming
60  /// and destroying. Does not support promises. The function is known to
61  /// suspend at most once during its execution, and the return value of
62  /// the continuation is void.
63  RetconOnce,
64 
65  /// The "async continuation" lowering, where each suspend point creates a
66  /// single continuation function. The continuation function is available as an
67  /// intrinsic.
68  Async,
69 };
70 
71 // Holds structural Coroutine Intrinsics for a particular function and other
72 // values used during CoroSplit pass.
80 
81  // Field indexes for special fields in the switch lowering.
83  enum {
85  Destroy
86 
87  // The promise field is always at a fixed offset from the start of
88  // frame given its type, but the index isn't a constant for all
89  // possible frames.
90 
91  // The switch-index field isn't at a fixed offset or index, either;
92  // we just work it in where it fits best.
93  };
94  };
95 
97 
103 
104  /// This would only be true if optimization are enabled.
106 
111  unsigned IndexField;
112  unsigned IndexAlign;
113  unsigned IndexOffset;
116  };
117 
124  };
125 
130  unsigned ContextArgNo;
133  uint64_t FrameOffset; // Start of the frame.
134  uint64_t ContextSize; // Includes frame size.
136 
137  Align getContextAlignment() const { return Align(ContextAlignment); }
138  };
139 
140  union {
144  };
145 
148  return cast<CoroIdInst>(CoroBegin->getId());
149  }
150 
154  return cast<AnyCoroIdRetconInst>(CoroBegin->getId());
155  }
156 
159  return cast<CoroIdAsyncInst>(CoroBegin->getId());
160  }
161 
162  unsigned getSwitchIndexField() const {
164  assert(FrameTy && "frame type not assigned");
165  return SwitchLowering.IndexField;
166  }
169  assert(FrameTy && "frame type not assigned");
170  return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
171  }
173  return ConstantInt::get(getIndexType(), Value);
174  }
175 
178  assert(FrameTy && "frame type not assigned");
179  return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
180  }
181 
183  switch (ABI) {
184  case coro::ABI::Switch:
185  return FunctionType::get(Type::getVoidTy(FrameTy->getContext()),
186  FrameTy->getPointerTo(), /*IsVarArg*/false);
187  case coro::ABI::Retcon:
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 
201  auto FTy = CoroBegin->getFunction()->getFunctionType();
202 
203  // The safety of all this is checked by checkWFRetconPrototype.
204  if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
205  return STy->elements().slice(1);
206  } else {
207  return ArrayRef<Type*>();
208  }
209  }
210 
214 
215  // The safety of all this is checked by checkWFRetconPrototype.
216  auto FTy = RetconLowering.ResumePrototype->getFunctionType();
217  return FTy->params().slice(1);
218  }
219 
221  switch (ABI) {
222  case coro::ABI::Switch:
223  return CallingConv::Fast;
224 
225  case coro::ABI::Retcon:
227  return RetconLowering.ResumePrototype->getCallingConv();
228  case coro::ABI::Async:
229  return AsyncLowering.AsyncCC;
230  }
231  llvm_unreachable("Unknown coro::ABI enum");
232  }
233 
235  if (ABI == coro::ABI::Switch)
236  return SwitchLowering.PromiseAlloca;
237  return nullptr;
238  }
239 
241  if (auto *I = dyn_cast<Instruction>(FramePtr))
242  return I->getNextNode();
243  return &cast<Argument>(FramePtr)->getParent()->getEntryBlock().front();
244  }
245 
246  /// Allocate memory according to the rules of the active lowering.
247  ///
248  /// \param CG - if non-null, will be updated for the new call
249  Value *emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const;
250 
251  /// Deallocate memory according to the rules of the active lowering.
252  ///
253  /// \param CG - if non-null, will be updated for the new call
254  void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const;
255 
256  Shape() = default;
257  explicit Shape(Function &F, bool OptimizeFrame = false)
258  : OptimizeFrame(OptimizeFrame) {
259  buildFrom(F);
260  }
261  void buildFrom(Function &F);
262 };
263 
264 void buildCoroutineFrame(Function &F, Shape &Shape);
265 CallInst *createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
267 } // End namespace coro.
268 } // End namespace llvm
269 
270 #endif
llvm::coro::Shape::CoroSizes
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition: CoroInternal.h:76
llvm::coro::Shape::getInsertPtAfterFramePtr
Instruction * getInsertPtAfterFramePtr() const
Definition: CoroInternal.h:240
llvm::coro::createMustTailCall
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, ArrayRef< Value * > Arguments, IRBuilder<> &)
Definition: CoroSplit.cpp:1675
llvm::coro::Shape::AsyncLoweringStorage::FrameOffset
uint64_t FrameOffset
Definition: CoroInternal.h:133
llvm::coro::Shape::RetconLoweringStorage::ResumePrototype
Function * ResumePrototype
Definition: CoroInternal.h:119
llvm::coro::LowererBase::NullPtr
ConstantPointerNull *const NullPtr
Definition: CoroInternal.h:40
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:141
llvm::coro::Shape::FrameTy
StructType * FrameTy
Definition: CoroInternal.h:98
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:1181
llvm::CallingConv::Fast
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
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:37
llvm::SmallDenseMap
Definition: DenseMap.h:880
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:129
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:127
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:96
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:234
llvm::coro::Shape::SwitchLoweringStorage::ResumeSwitch
SwitchInst * ResumeSwitch
Definition: CoroInternal.h:108
llvm::coro::buildCoroutineFrame
void buildCoroutineFrame(Function &F, Shape &Shape)
Definition: CoroFrame.cpp:2653
llvm::coro::Shape::getAsyncCoroId
CoroIdAsyncInst * getAsyncCoroId() const
Definition: CoroInternal.h:157
llvm::coro::Shape::SwitchLoweringStorage::PromiseAlloca
AllocaInst * PromiseAlloca
Definition: CoroInternal.h:109
llvm::coro::Shape::getResumeFunctionCC
CallingConv::ID getResumeFunctionCC() const
Definition: CoroInternal.h:220
llvm::coro::Shape::AsyncLoweringStorage::ContextHeaderSize
uint64_t ContextHeaderSize
Definition: CoroInternal.h:131
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::coro::Shape::SwitchLoweringStorage::HasUnwindCoroEnd
bool HasUnwindCoroEnd
Definition: CoroInternal.h:115
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:187
llvm::ConstantPointerNull
A constant pointer value that points to null.
Definition: Constants.h:535
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:102
llvm::coro::Shape::RetconLoweringStorage::IsFrameInlineInStorage
bool IsFrameInlineInStorage
Definition: CoroInternal.h:123
llvm::coro::Shape::RetconLoweringStorage
Definition: CoroInternal.h:118
llvm::coro::Shape::getRetconResumeTypes
ArrayRef< Type * > getRetconResumeTypes() const
Definition: CoroInternal.h:211
llvm::coro::Shape::AsyncLoweringStorage::AsyncFuncPointer
GlobalVariable * AsyncFuncPointer
Definition: CoroInternal.h:135
llvm::coro::Shape::getRetconResultTypes
ArrayRef< Type * > getRetconResultTypes() const
Definition: CoroInternal.h:198
llvm::coro::declaresAnyIntrinsic
bool declaresAnyIntrinsic(const Module &M)
Definition: Coroutines.cpp:105
llvm::coro::Shape::CoroSuspends
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition: CoroInternal.h:78
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::IntegerType
Class to represent integer types.
Definition: DerivedTypes.h:40
llvm::coro::Shape::SwitchLoweringStorage
Definition: CoroInternal.h:107
llvm::coro::Shape::CoroEnds
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition: CoroInternal.h:75
llvm::coro::Shape::SwitchFieldIndex
Definition: CoroInternal.h:82
llvm::coro::Shape::RetconLoweringStorage::Alloc
Function * Alloc
Definition: CoroInternal.h:120
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:114
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:879
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:99
llvm::coro::Shape::SwitchFieldIndex::Resume
@ Resume
Definition: CoroInternal.h:84
llvm::coro::LowererBase::LowererBase
LowererBase(Module &M)
Definition: Coroutines.cpp:38
llvm::coro::Shape::getIndexType
IntegerType * getIndexType() const
Definition: CoroInternal.h:167
llvm::coro::Shape
Definition: CoroInternal.h:73
llvm::coro::Shape::AsyncLowering
AsyncLoweringStorage AsyncLowering
Definition: CoroInternal.h:143
llvm::coro::Shape::AsyncLoweringStorage::ContextAlignment
uint64_t ContextAlignment
Definition: CoroInternal.h:132
llvm::DbgVariableIntrinsic
This is the common base class for debug info intrinsics for variables.
Definition: IntrinsicInst.h:153
llvm::coro::Shape::SwiftErrorOps
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition: CoroInternal.h:79
uint64_t
llvm::coro::Shape::SwitchLoweringStorage::IndexOffset
unsigned IndexOffset
Definition: CoroInternal.h:113
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
llvm::coro::Shape::SwitchLoweringStorage::IndexAlign
unsigned IndexAlign
Definition: CoroInternal.h:112
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:128
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.
Ptr
@ Ptr
Definition: TargetLibraryInfo.cpp:60
llvm::coro::Shape::OptimizeFrame
bool OptimizeFrame
This would only be true if optimization are enabled.
Definition: CoroInternal.h:105
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:134
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:46
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:126
llvm::coro::Shape::CoroBegin
CoroBeginInst * CoroBegin
Definition: CoroInternal.h:74
llvm::coro::Shape::getResumeFunctionType
FunctionType * getResumeFunctionType() const
Definition: CoroInternal.h:182
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:110
llvm::coro::Shape::RetconLowering
RetconLoweringStorage RetconLowering
Definition: CoroInternal.h:142
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:2563
llvm::coro::Shape::CoroAligns
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition: CoroInternal.h:77
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:257
llvm::coro::Shape::getSwitchResumePointerType
PointerType * getSwitchResumePointerType() const
Definition: CoroInternal.h:176
llvm::coro::Shape::getIndex
ConstantInt * getIndex(uint64_t Value) const
Definition: CoroInternal.h:172
llvm::coro::LowererBase::TheModule
Module & TheModule
Definition: CoroInternal.h:36
Arguments
AMDGPU Lower Kernel Arguments
Definition: AMDGPULowerKernelArguments.cpp:242
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:146
llvm::coro::Shape::getSwitchIndexField
unsigned getSwitchIndexField() const
Definition: CoroInternal.h:162
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:151
llvm::coro::Shape::RetconLoweringStorage::ReturnBlock
BasicBlock * ReturnBlock
Definition: CoroInternal.h:122
llvm::coro::Shape::FrameSize
uint64_t FrameSize
Definition: CoroInternal.h:100
llvm::coro::Shape::AsyncLoweringStorage::ContextArgNo
unsigned ContextArgNo
Definition: CoroInternal.h:130
llvm::coro::LowererBase
Definition: CoroInternal.h:35
llvm::coro::LowererBase::ResumeFnType
FunctionType *const ResumeFnType
Definition: CoroInternal.h:39
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:101
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:38
llvm::SwitchInst
Multiway switch.
Definition: Instructions.h:3278
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:59
llvm::coro::Shape::AsyncLoweringStorage::getContextAlignment
Align getContextAlignment() const
Definition: CoroInternal.h:137
llvm::coro::Shape::RetconLoweringStorage::Dealloc
Function * Dealloc
Definition: CoroInternal.h:121
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::coro::Shape::SwitchLoweringStorage::IndexField
unsigned IndexField
Definition: CoroInternal.h:111
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103
llvm::coro::Shape::AsyncLoweringStorage
Definition: CoroInternal.h:126