LLVM  8.0.1
CoroEarly.cpp
Go to the documentation of this file.
1 //===- CoroEarly.cpp - Coroutine Early Function Pass ----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // This pass lowers coroutine intrinsics that hide the details of the exact
10 // calling convention for coroutine resume and destroy functions and details of
11 // the structure of the coroutine frame.
12 //===----------------------------------------------------------------------===//
13 
14 #include "CoroInternal.h"
15 #include "llvm/IR/CallSite.h"
16 #include "llvm/IR/IRBuilder.h"
17 #include "llvm/IR/InstIterator.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Pass.h"
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "coro-early"
24 
25 namespace {
26 // Created on demand if CoroEarly pass has work to do.
27 class Lowerer : public coro::LowererBase {
28  IRBuilder<> Builder;
29  PointerType *const AnyResumeFnPtrTy;
30  Constant *NoopCoro = nullptr;
31 
32  void lowerResumeOrDestroy(CallSite CS, CoroSubFnInst::ResumeKind);
33  void lowerCoroPromise(CoroPromiseInst *Intrin);
34  void lowerCoroDone(IntrinsicInst *II);
35  void lowerCoroNoop(IntrinsicInst *II);
36 
37 public:
38  Lowerer(Module &M)
39  : LowererBase(M), Builder(Context),
40  AnyResumeFnPtrTy(FunctionType::get(Type::getVoidTy(Context), Int8Ptr,
41  /*isVarArg=*/false)
42  ->getPointerTo()) {}
43  bool lowerEarlyIntrinsics(Function &F);
44 };
45 }
46 
47 // Replace a direct call to coro.resume or coro.destroy with an indirect call to
48 // an address returned by coro.subfn.addr intrinsic. This is done so that
49 // CGPassManager recognizes devirtualization when CoroElide pass replaces a call
50 // to coro.subfn.addr with an appropriate function address.
51 void Lowerer::lowerResumeOrDestroy(CallSite CS,
53  Value *ResumeAddr =
54  makeSubFnCall(CS.getArgOperand(0), Index, CS.getInstruction());
55  CS.setCalledFunction(ResumeAddr);
57 }
58 
59 // Coroutine promise field is always at the fixed offset from the beginning of
60 // the coroutine frame. i8* coro.promise(i8*, i1 from) intrinsic adds an offset
61 // to a passed pointer to move from coroutine frame to coroutine promise and
62 // vice versa. Since we don't know exactly which coroutine frame it is, we build
63 // a coroutine frame mock up starting with two function pointers, followed by a
64 // properly aligned coroutine promise field.
65 // TODO: Handle the case when coroutine promise alloca has align override.
66 void Lowerer::lowerCoroPromise(CoroPromiseInst *Intrin) {
67  Value *Operand = Intrin->getArgOperand(0);
68  unsigned Alignement = Intrin->getAlignment();
69  Type *Int8Ty = Builder.getInt8Ty();
70 
71  auto *SampleStruct =
72  StructType::get(Context, {AnyResumeFnPtrTy, AnyResumeFnPtrTy, Int8Ty});
73  const DataLayout &DL = TheModule.getDataLayout();
74  int64_t Offset = alignTo(
75  DL.getStructLayout(SampleStruct)->getElementOffset(2), Alignement);
76  if (Intrin->isFromPromise())
77  Offset = -Offset;
78 
79  Builder.SetInsertPoint(Intrin);
80  Value *Replacement =
81  Builder.CreateConstInBoundsGEP1_32(Int8Ty, Operand, Offset);
82 
83  Intrin->replaceAllUsesWith(Replacement);
84  Intrin->eraseFromParent();
85 }
86 
87 // When a coroutine reaches final suspend point, it zeros out ResumeFnAddr in
88 // the coroutine frame (it is UB to resume from a final suspend point).
89 // The llvm.coro.done intrinsic is used to check whether a coroutine is
90 // suspended at the final suspend point or not.
91 void Lowerer::lowerCoroDone(IntrinsicInst *II) {
92  Value *Operand = II->getArgOperand(0);
93 
94  // ResumeFnAddr is the first pointer sized element of the coroutine frame.
95  auto *FrameTy = Int8Ptr;
96  PointerType *FramePtrTy = FrameTy->getPointerTo();
97 
98  Builder.SetInsertPoint(II);
99  auto *BCI = Builder.CreateBitCast(Operand, FramePtrTy);
100  auto *Gep = Builder.CreateConstInBoundsGEP1_32(FrameTy, BCI, 0);
101  auto *Load = Builder.CreateLoad(Gep);
102  auto *Cond = Builder.CreateICmpEQ(Load, NullPtr);
103 
104  II->replaceAllUsesWith(Cond);
105  II->eraseFromParent();
106 }
107 
108 void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
109  if (!NoopCoro) {
110  LLVMContext &C = Builder.getContext();
111  Module &M = *II->getModule();
112 
113  // Create a noop.frame struct type.
114  StructType *FrameTy = StructType::create(C, "NoopCoro.Frame");
115  auto *FramePtrTy = FrameTy->getPointerTo();
116  auto *FnTy = FunctionType::get(Type::getVoidTy(C), FramePtrTy,
117  /*IsVarArgs=*/false);
118  auto *FnPtrTy = FnTy->getPointerTo();
119  FrameTy->setBody({FnPtrTy, FnPtrTy});
120 
121  // Create a Noop function that does nothing.
122  Function *NoopFn =
123  Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage,
124  "NoopCoro.ResumeDestroy", &M);
126  auto *Entry = BasicBlock::Create(C, "entry", NoopFn);
127  ReturnInst::Create(C, Entry);
128 
129  // Create a constant struct for the frame.
130  Constant* Values[] = {NoopFn, NoopFn};
131  Constant* NoopCoroConst = ConstantStruct::get(FrameTy, Values);
132  NoopCoro = new GlobalVariable(M, NoopCoroConst->getType(), /*isConstant=*/true,
133  GlobalVariable::PrivateLinkage, NoopCoroConst,
134  "NoopCoro.Frame.Const");
135  }
136 
137  Builder.SetInsertPoint(II);
138  auto *NoopCoroVoidPtr = Builder.CreateBitCast(NoopCoro, Int8Ptr);
139  II->replaceAllUsesWith(NoopCoroVoidPtr);
140  II->eraseFromParent();
141 }
142 
143 // Prior to CoroSplit, calls to coro.begin needs to be marked as NoDuplicate,
144 // as CoroSplit assumes there is exactly one coro.begin. After CoroSplit,
145 // NoDuplicate attribute will be removed from coro.begin otherwise, it will
146 // interfere with inlining.
147 static void setCannotDuplicate(CoroIdInst *CoroId) {
148  for (User *U : CoroId->users())
149  if (auto *CB = dyn_cast<CoroBeginInst>(U))
150  CB->setCannotDuplicate();
151 }
152 
153 bool Lowerer::lowerEarlyIntrinsics(Function &F) {
154  bool Changed = false;
155  CoroIdInst *CoroId = nullptr;
157  for (auto IB = inst_begin(F), IE = inst_end(F); IB != IE;) {
158  Instruction &I = *IB++;
159  if (auto CS = CallSite(&I)) {
160  switch (CS.getIntrinsicID()) {
161  default:
162  continue;
164  CoroFrees.push_back(cast<CoroFreeInst>(&I));
165  break;
167  // Make sure that final suspend point is not duplicated as CoroSplit
168  // pass expects that there is at most one final suspend point.
169  if (cast<CoroSuspendInst>(&I)->isFinal())
170  CS.setCannotDuplicate();
171  break;
172  case Intrinsic::coro_end:
173  // Make sure that fallthrough coro.end is not duplicated as CoroSplit
174  // pass expects that there is at most one fallthrough coro.end.
175  if (cast<CoroEndInst>(&I)->isFallthrough())
176  CS.setCannotDuplicate();
177  break;
179  lowerCoroNoop(cast<IntrinsicInst>(&I));
180  break;
181  case Intrinsic::coro_id:
182  // Mark a function that comes out of the frontend that has a coro.id
183  // with a coroutine attribute.
184  if (auto *CII = cast<CoroIdInst>(&I)) {
185  if (CII->getInfo().isPreSplit()) {
187  setCannotDuplicate(CII);
188  CII->setCoroutineSelf();
189  CoroId = cast<CoroIdInst>(&I);
190  }
191  }
192  break;
194  lowerResumeOrDestroy(CS, CoroSubFnInst::ResumeIndex);
195  break;
197  lowerResumeOrDestroy(CS, CoroSubFnInst::DestroyIndex);
198  break;
200  lowerCoroPromise(cast<CoroPromiseInst>(&I));
201  break;
203  lowerCoroDone(cast<IntrinsicInst>(&I));
204  break;
205  }
206  Changed = true;
207  }
208  }
209  // Make sure that all CoroFree reference the coro.id intrinsic.
210  // Token type is not exposed through coroutine C/C++ builtins to plain C, so
211  // we allow specifying none and fixing it up here.
212  if (CoroId)
213  for (CoroFreeInst *CF : CoroFrees)
214  CF->setArgOperand(0, CoroId);
215  return Changed;
216 }
217 
218 //===----------------------------------------------------------------------===//
219 // Top Level Driver
220 //===----------------------------------------------------------------------===//
221 
222 namespace {
223 
224 struct CoroEarly : public FunctionPass {
225  static char ID; // Pass identification, replacement for typeid.
226  CoroEarly() : FunctionPass(ID) {
228  }
229 
230  std::unique_ptr<Lowerer> L;
231 
232  // This pass has work to do only if we find intrinsics we are going to lower
233  // in the module.
234  bool doInitialization(Module &M) override {
236  M, {"llvm.coro.id", "llvm.coro.destroy", "llvm.coro.done",
237  "llvm.coro.end", "llvm.coro.noop", "llvm.coro.free",
238  "llvm.coro.promise", "llvm.coro.resume", "llvm.coro.suspend"}))
239  L = llvm::make_unique<Lowerer>(M);
240  return false;
241  }
242 
243  bool runOnFunction(Function &F) override {
244  if (!L)
245  return false;
246 
247  return L->lowerEarlyIntrinsics(F);
248  }
249 
250  void getAnalysisUsage(AnalysisUsage &AU) const override {
251  AU.setPreservesCFG();
252  }
253  StringRef getPassName() const override {
254  return "Lower early coroutine intrinsics";
255  }
256 };
257 }
258 
259 char CoroEarly::ID = 0;
260 INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics",
261  false, false)
262 
263 Pass *llvm::createCoroEarlyPass() { return new CoroEarly(); }
Pass interface - Implemented by all &#39;passes&#39;.
Definition: Pass.h:81
uint64_t CallInst * C
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:68
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & Context
This represents the llvm.coro.promise instruction.
Definition: CoroInstr.h:245
This represents the llvm.coro.alloc instruction.
Definition: CoroInstr.h:82
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void initializeCoroEarlyPass(PassRegistry &)
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:57
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:705
Pass * createCoroEarlyPass()
Lower coroutine intrinsics that are not needed by later passes.
F(f)
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:685
unsigned getAlignment() const
Definition: CoroInstr.h:252
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1135
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:132
Class to represent struct types.
Definition: DerivedTypes.h:201
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:652
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:743
InstrTy * getInstruction() const
Definition: CallSite.h:92
INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics", false, false) Pass *llvm
Definition: CoroEarly.cpp:260
static StructType * get(LLVMContext &Context, ArrayRef< Type *> Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition: Type.cpp:342
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:43
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
ValTy * getArgOperand(unsigned i) const
Definition: CallSite.h:297
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of the intrinsic called by this CallSite, or Intrinsic::not_intrinsic if the ...
Definition: CallSite.h:134
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
void setBody(ArrayRef< Type *> Elements, bool isPacked=false)
Specify a body for an opaque identified type.
Definition: Type.cpp:369
Class to represent pointers.
Definition: DerivedTypes.h:467
static bool runOnFunction(Function &F, bool PostInlining)
void setCallingConv(CallingConv::ID CC)
Definition: Function.h:217
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:136
#define CORO_PRESPLIT_ATTR
Definition: CoroInternal.h:38
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
This is an important base class in LLVM.
Definition: Constant.h:42
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:161
void setCallingConv(CallingConv::ID CC)
Set the calling convention of the call.
Definition: CallSite.h:316
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:297
static Constant * get(StructType *T, ArrayRef< Constant *> V)
Definition: Constants.cpp:1044
bool isFromPromise() const
Definition: CoroInstr.h:249
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
This represents the llvm.coro.free instruction.
Definition: CoroInstr.h:199
void setCannotDuplicate()
Definition: CallSite.h:516
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
Module.h This file contains the declarations for the Module class.
#define UNPREPARED_FOR_SPLIT
Definition: CoroInternal.h:39
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:286
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Definition: Instruction.cpp:56
iterator_range< user_iterator > users()
Definition: Value.h:400
#define I(x, y, z)
Definition: MD5.cpp:58
static void setCannotDuplicate(CoroIdInst *CoroId)
Definition: CoroEarly.cpp:147
LLVM Value Representation.
Definition: Value.h:73
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:437
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
Definition: Coroutines.cpp:140
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.h:230
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:133
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:174
void setCalledFunction(Value *V)
Set the callee to the specified value.
Definition: CallSite.h:126
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:44