LLVM  6.0.0svn
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 
31  void lowerResumeOrDestroy(CallSite CS, CoroSubFnInst::ResumeKind);
32  void lowerCoroPromise(CoroPromiseInst *Intrin);
33  void lowerCoroDone(IntrinsicInst *II);
34 
35 public:
36  Lowerer(Module &M)
37  : LowererBase(M), Builder(Context),
38  AnyResumeFnPtrTy(FunctionType::get(Type::getVoidTy(Context), Int8Ptr,
39  /*isVarArg=*/false)
40  ->getPointerTo()) {}
41  bool lowerEarlyIntrinsics(Function &F);
42 };
43 }
44 
45 // Replace a direct call to coro.resume or coro.destroy with an indirect call to
46 // an address returned by coro.subfn.addr intrinsic. This is done so that
47 // CGPassManager recognizes devirtualization when CoroElide pass replaces a call
48 // to coro.subfn.addr with an appropriate function address.
49 void Lowerer::lowerResumeOrDestroy(CallSite CS,
51  Value *ResumeAddr =
52  makeSubFnCall(CS.getArgOperand(0), Index, CS.getInstruction());
53  CS.setCalledFunction(ResumeAddr);
55 }
56 
57 // Coroutine promise field is always at the fixed offset from the beginning of
58 // the coroutine frame. i8* coro.promise(i8*, i1 from) intrinsic adds an offset
59 // to a passed pointer to move from coroutine frame to coroutine promise and
60 // vice versa. Since we don't know exactly which coroutine frame it is, we build
61 // a coroutine frame mock up starting with two function pointers, followed by a
62 // properly aligned coroutine promise field.
63 // TODO: Handle the case when coroutine promise alloca has align override.
64 void Lowerer::lowerCoroPromise(CoroPromiseInst *Intrin) {
65  Value *Operand = Intrin->getArgOperand(0);
66  unsigned Alignement = Intrin->getAlignment();
67  Type *Int8Ty = Builder.getInt8Ty();
68 
69  auto *SampleStruct =
70  StructType::get(Context, {AnyResumeFnPtrTy, AnyResumeFnPtrTy, Int8Ty});
71  const DataLayout &DL = TheModule.getDataLayout();
72  int64_t Offset = alignTo(
73  DL.getStructLayout(SampleStruct)->getElementOffset(2), Alignement);
74  if (Intrin->isFromPromise())
75  Offset = -Offset;
76 
77  Builder.SetInsertPoint(Intrin);
78  Value *Replacement =
79  Builder.CreateConstInBoundsGEP1_32(Int8Ty, Operand, Offset);
80 
81  Intrin->replaceAllUsesWith(Replacement);
82  Intrin->eraseFromParent();
83 }
84 
85 // When a coroutine reaches final suspend point, it zeros out ResumeFnAddr in
86 // the coroutine frame (it is UB to resume from a final suspend point).
87 // The llvm.coro.done intrinsic is used to check whether a coroutine is
88 // suspended at the final suspend point or not.
89 void Lowerer::lowerCoroDone(IntrinsicInst *II) {
90  Value *Operand = II->getArgOperand(0);
91 
92  // ResumeFnAddr is the first pointer sized element of the coroutine frame.
93  auto *FrameTy = Int8Ptr;
94  PointerType *FramePtrTy = FrameTy->getPointerTo();
95 
96  Builder.SetInsertPoint(II);
97  auto *BCI = Builder.CreateBitCast(Operand, FramePtrTy);
98  auto *Gep = Builder.CreateConstInBoundsGEP1_32(FrameTy, BCI, 0);
99  auto *Load = Builder.CreateLoad(Gep);
100  auto *Cond = Builder.CreateICmpEQ(Load, NullPtr);
101 
102  II->replaceAllUsesWith(Cond);
103  II->eraseFromParent();
104 }
105 
106 // Prior to CoroSplit, calls to coro.begin needs to be marked as NoDuplicate,
107 // as CoroSplit assumes there is exactly one coro.begin. After CoroSplit,
108 // NoDuplicate attribute will be removed from coro.begin otherwise, it will
109 // interfere with inlining.
110 static void setCannotDuplicate(CoroIdInst *CoroId) {
111  for (User *U : CoroId->users())
112  if (auto *CB = dyn_cast<CoroBeginInst>(U))
113  CB->setCannotDuplicate();
114 }
115 
116 bool Lowerer::lowerEarlyIntrinsics(Function &F) {
117  bool Changed = false;
118  CoroIdInst *CoroId = nullptr;
120  for (auto IB = inst_begin(F), IE = inst_end(F); IB != IE;) {
121  Instruction &I = *IB++;
122  if (auto CS = CallSite(&I)) {
123  switch (CS.getIntrinsicID()) {
124  default:
125  continue;
126  case Intrinsic::coro_free:
127  CoroFrees.push_back(cast<CoroFreeInst>(&I));
128  break;
129  case Intrinsic::coro_suspend:
130  // Make sure that final suspend point is not duplicated as CoroSplit
131  // pass expects that there is at most one final suspend point.
132  if (cast<CoroSuspendInst>(&I)->isFinal())
133  CS.setCannotDuplicate();
134  break;
135  case Intrinsic::coro_end:
136  // Make sure that fallthrough coro.end is not duplicated as CoroSplit
137  // pass expects that there is at most one fallthrough coro.end.
138  if (cast<CoroEndInst>(&I)->isFallthrough())
139  CS.setCannotDuplicate();
140  break;
141  case Intrinsic::coro_id:
142  // Mark a function that comes out of the frontend that has a coro.id
143  // with a coroutine attribute.
144  if (auto *CII = cast<CoroIdInst>(&I)) {
145  if (CII->getInfo().isPreSplit()) {
147  setCannotDuplicate(CII);
148  CII->setCoroutineSelf();
149  CoroId = cast<CoroIdInst>(&I);
150  }
151  }
152  break;
153  case Intrinsic::coro_resume:
154  lowerResumeOrDestroy(CS, CoroSubFnInst::ResumeIndex);
155  break;
156  case Intrinsic::coro_destroy:
157  lowerResumeOrDestroy(CS, CoroSubFnInst::DestroyIndex);
158  break;
159  case Intrinsic::coro_promise:
160  lowerCoroPromise(cast<CoroPromiseInst>(&I));
161  break;
162  case Intrinsic::coro_done:
163  lowerCoroDone(cast<IntrinsicInst>(&I));
164  break;
165  }
166  Changed = true;
167  }
168  }
169  // Make sure that all CoroFree reference the coro.id intrinsic.
170  // Token type is not exposed through coroutine C/C++ builtins to plain C, so
171  // we allow specifying none and fixing it up here.
172  if (CoroId)
173  for (CoroFreeInst *CF : CoroFrees)
174  CF->setArgOperand(0, CoroId);
175  return Changed;
176 }
177 
178 //===----------------------------------------------------------------------===//
179 // Top Level Driver
180 //===----------------------------------------------------------------------===//
181 
182 namespace {
183 
184 struct CoroEarly : public FunctionPass {
185  static char ID; // Pass identification, replacement for typeid.
186  CoroEarly() : FunctionPass(ID) {
188  }
189 
190  std::unique_ptr<Lowerer> L;
191 
192  // This pass has work to do only if we find intrinsics we are going to lower
193  // in the module.
194  bool doInitialization(Module &M) override {
195  if (coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.destroy",
196  "llvm.coro.done", "llvm.coro.end",
197  "llvm.coro.free", "llvm.coro.promise",
198  "llvm.coro.resume", "llvm.coro.suspend"}))
199  L = llvm::make_unique<Lowerer>(M);
200  return false;
201  }
202 
203  bool runOnFunction(Function &F) override {
204  if (!L)
205  return false;
206 
207  return L->lowerEarlyIntrinsics(F);
208  }
209 
210  void getAnalysisUsage(AnalysisUsage &AU) const override {
211  AU.setPreservesCFG();
212  }
213  StringRef getPassName() const override {
214  return "Lower early coroutine intrinsics";
215  }
216 };
217 }
218 
219 char CoroEarly::ID = 0;
220 INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics",
221  false, false)
222 
223 Pass *llvm::createCoroEarlyPass() { return new CoroEarly(); }
Pass interface - Implemented by all &#39;passes&#39;.
Definition: Pass.h:81
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:43
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:69
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:109
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
Compute iterated dominance frontiers using a linear time algorithm.
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:63
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:677
unsigned getAlignment() const
Definition: CoroInstr.h:252
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:132
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:639
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:668
InstrTy * getInstruction() const
Definition: CallSite.h:92
INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics", false, false) Pass *llvm
Definition: CoroEarly.cpp:220
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:336
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:430
Class to represent pointers.
Definition: DerivedTypes.h:467
static bool runOnFunction(Function &F, bool PostInlining)
#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
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
bool isFromPromise() const
Definition: CoroInstr.h:249
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:864
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:285
iterator_range< user_iterator > users()
Definition: Value.h:401
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
#define I(x, y, z)
Definition: MD5.cpp:58
static void setCannotDuplicate(CoroIdInst *CoroId)
Definition: CoroEarly.cpp:110
LLVM Value Representation.
Definition: Value.h:73
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
Definition: Coroutines.cpp:138
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition: Function.h:211
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