LLVM  9.0.0svn
CoroInstr.h
Go to the documentation of this file.
1 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- 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 defines classes that make it really easy to deal with intrinsic
9 // functions with the isa/dyncast family of functions. In particular, this
10 // allows you to do things like:
11 //
12 // if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13 // ... SF->getFrame() ...
14 //
15 // All intrinsic function calls are instances of the call instruction, so these
16 // are all subclasses of the CallInst class. Note that none of these classes
17 // has state or virtual methods, which is an important part of this gross/neat
18 // hack working.
19 //
20 // The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
21 // coroutine intrinsic wrappers here since they are only used by the passes in
22 // the Coroutine library.
23 //===----------------------------------------------------------------------===//
24 
25 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
27 
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 
31 namespace llvm {
32 
33 /// This class represents the llvm.coro.subfn.addr instruction.
35  enum { FrameArg, IndexArg };
36 
37 public:
38  enum ResumeKind {
39  RestartTrigger = -1,
44  IndexFirst = RestartTrigger
45  };
46 
47  Value *getFrame() const { return getArgOperand(FrameArg); }
48  ResumeKind getIndex() const {
49  int64_t Index = getRawIndex()->getValue().getSExtValue();
50  assert(Index >= IndexFirst && Index < IndexLast &&
51  "unexpected CoroSubFnInst index argument");
52  return static_cast<ResumeKind>(Index);
53  }
54 
56  return cast<ConstantInt>(getArgOperand(IndexArg));
57  }
58 
59  // Methods to support type inquiry through isa, cast, and dyn_cast:
60  static bool classof(const IntrinsicInst *I) {
61  return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
62  }
63  static bool classof(const Value *V) {
64  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
65  }
66 };
67 
68 /// This represents the llvm.coro.alloc instruction.
70 public:
71  // Methods to support type inquiry through isa, cast, and dyn_cast:
72  static bool classof(const IntrinsicInst *I) {
73  return I->getIntrinsicID() == Intrinsic::coro_alloc;
74  }
75  static bool classof(const Value *V) {
76  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
77  }
78 };
79 
80 /// This represents the llvm.coro.alloc instruction.
82  enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
83 
84 public:
86  for (User *U : users())
87  if (auto *CA = dyn_cast<CoroAllocInst>(U))
88  return CA;
89  return nullptr;
90  }
91 
93  for (User *U : users())
94  if (auto *II = dyn_cast<IntrinsicInst>(U))
95  if (II->getIntrinsicID() == Intrinsic::coro_begin)
96  return II;
97  llvm_unreachable("no coro.begin associated with coro.id");
98  }
99 
101  Value *Arg = getArgOperand(PromiseArg);
102  return isa<ConstantPointerNull>(Arg)
103  ? nullptr
104  : cast<AllocaInst>(Arg->stripPointerCasts());
105  }
106 
107  void clearPromise() {
108  Value *Arg = getArgOperand(PromiseArg);
109  setArgOperand(PromiseArg,
111  if (isa<AllocaInst>(Arg))
112  return;
113  assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
114  "unexpected instruction designating the promise");
115  // TODO: Add a check that any remaining users of Inst are after coro.begin
116  // or add code to move the users after coro.begin.
117  auto *Inst = cast<Instruction>(Arg);
118  if (Inst->use_empty()) {
119  Inst->eraseFromParent();
120  return;
121  }
122  Inst->moveBefore(getCoroBegin()->getNextNode());
123  }
124 
125  // Info argument of coro.id is
126  // fresh out of the frontend: null ;
127  // outlined : {Init, Return, Susp1, Susp2, ...} ;
128  // postsplit : [resume, destroy, cleanup] ;
129  //
130  // If parts of the coroutine were outlined to protect against undesirable
131  // code motion, these functions will be stored in a struct literal referred to
132  // by the Info parameter. Note: this is only needed before coroutine is split.
133  //
134  // After coroutine is split, resume functions are stored in an array
135  // referred to by this parameter.
136 
137  struct Info {
138  ConstantStruct *OutlinedParts = nullptr;
139  ConstantArray *Resumers = nullptr;
140 
141  bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
142  bool isPostSplit() const { return Resumers != nullptr; }
143  bool isPreSplit() const { return !isPostSplit(); }
144  };
145  Info getInfo() const {
146  Info Result;
147  auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
148  if (!GV)
149  return Result;
150 
151  assert(GV->isConstant() && GV->hasDefinitiveInitializer());
152  Constant *Initializer = GV->getInitializer();
153  if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
154  return Result;
155 
156  Result.Resumers = cast<ConstantArray>(Initializer);
157  return Result;
158  }
159  Constant *getRawInfo() const {
160  return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
161  }
162 
163  void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
164 
166  return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
167  }
169  assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
170  "Coroutine argument is already assigned");
171  auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
172  setArgOperand(CoroutineArg,
173  ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
174  }
175 
176  // Methods to support type inquiry through isa, cast, and dyn_cast:
177  static bool classof(const IntrinsicInst *I) {
178  return I->getIntrinsicID() == Intrinsic::coro_id;
179  }
180  static bool classof(const Value *V) {
181  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
182  }
183 };
184 
185 /// This represents the llvm.coro.frame instruction.
187 public:
188  // Methods to support type inquiry through isa, cast, and dyn_cast:
189  static bool classof(const IntrinsicInst *I) {
190  return I->getIntrinsicID() == Intrinsic::coro_frame;
191  }
192  static bool classof(const Value *V) {
193  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
194  }
195 };
196 
197 /// This represents the llvm.coro.free instruction.
199  enum { IdArg, FrameArg };
200 
201 public:
202  Value *getFrame() const { return getArgOperand(FrameArg); }
203 
204  // Methods to support type inquiry through isa, cast, and dyn_cast:
205  static bool classof(const IntrinsicInst *I) {
206  return I->getIntrinsicID() == Intrinsic::coro_free;
207  }
208  static bool classof(const Value *V) {
209  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
210  }
211 };
212 
213 /// This class represents the llvm.coro.begin instruction.
215  enum { IdArg, MemArg };
216 
217 public:
218  CoroIdInst *getId() const { return cast<CoroIdInst>(getArgOperand(IdArg)); }
219 
220  Value *getMem() const { return getArgOperand(MemArg); }
221 
222  // Methods for support type inquiry through isa, cast, and dyn_cast:
223  static bool classof(const IntrinsicInst *I) {
224  return I->getIntrinsicID() == Intrinsic::coro_begin;
225  }
226  static bool classof(const Value *V) {
227  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
228  }
229 };
230 
231 /// This represents the llvm.coro.save instruction.
233 public:
234  // Methods to support type inquiry through isa, cast, and dyn_cast:
235  static bool classof(const IntrinsicInst *I) {
236  return I->getIntrinsicID() == Intrinsic::coro_save;
237  }
238  static bool classof(const Value *V) {
239  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
240  }
241 };
242 
243 /// This represents the llvm.coro.promise instruction.
245  enum { FrameArg, AlignArg, FromArg };
246 
247 public:
248  bool isFromPromise() const {
249  return cast<Constant>(getArgOperand(FromArg))->isOneValue();
250  }
251  unsigned getAlignment() const {
252  return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
253  }
254 
255  // Methods to support type inquiry through isa, cast, and dyn_cast:
256  static bool classof(const IntrinsicInst *I) {
257  return I->getIntrinsicID() == Intrinsic::coro_promise;
258  }
259  static bool classof(const Value *V) {
260  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
261  }
262 };
263 
264 /// This represents the llvm.coro.suspend instruction.
266  enum { SaveArg, FinalArg };
267 
268 public:
270  Value *Arg = getArgOperand(SaveArg);
271  if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
272  return SI;
273  assert(isa<ConstantTokenNone>(Arg));
274  return nullptr;
275  }
276  bool isFinal() const {
277  return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
278  }
279 
280  // Methods to support type inquiry through isa, cast, and dyn_cast:
281  static bool classof(const IntrinsicInst *I) {
282  return I->getIntrinsicID() == Intrinsic::coro_suspend;
283  }
284  static bool classof(const Value *V) {
285  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
286  }
287 };
288 
289 /// This represents the llvm.coro.size instruction.
291 public:
292  // Methods to support type inquiry through isa, cast, and dyn_cast:
293  static bool classof(const IntrinsicInst *I) {
294  return I->getIntrinsicID() == Intrinsic::coro_size;
295  }
296  static bool classof(const Value *V) {
297  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
298  }
299 };
300 
301 /// This represents the llvm.coro.end instruction.
303  enum { FrameArg, UnwindArg };
304 
305 public:
306  bool isFallthrough() const { return !isUnwind(); }
307  bool isUnwind() const {
308  return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
309  }
310 
311  // Methods to support type inquiry through isa, cast, and dyn_cast:
312  static bool classof(const IntrinsicInst *I) {
313  return I->getIntrinsicID() == Intrinsic::coro_end;
314  }
315  static bool classof(const Value *V) {
316  return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
317  }
318 };
319 
320 } // End namespace llvm.
321 
322 #endif
uint64_t CallInst * C
This represents the llvm.coro.promise instruction.
Definition: CoroInstr.h:244
This represents the llvm.coro.alloc instruction.
Definition: CoroInstr.h:81
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:223
IntrinsicInst * getCoroBegin()
Definition: CoroInstr.h:92
Info getInfo() const
Definition: CoroInstr.h:145
unsigned getAlignment() const
Definition: CoroInstr.h:251
ConstantInt * getRawIndex() const
Definition: CoroInstr.h:55
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:177
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:312
static bool classof(const Value *V)
Definition: CoroInstr.h:226
This represents the llvm.coro.suspend instruction.
Definition: CoroInstr.h:265
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:189
AllocaInst * getPromise() const
Definition: CoroInstr.h:100
This class represents the llvm.coro.subfn.addr instruction.
Definition: CoroInstr.h:34
ConstantStruct * OutlinedParts
Definition: CoroInstr.h:138
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:235
bool isPreSplit() const
Definition: CoroInstr.h:143
This represents the llvm.coro.alloc instruction.
Definition: CoroInstr.h:69
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:60
void setCoroutineSelf()
Definition: CoroInstr.h:168
bool isFallthrough() const
Definition: CoroInstr.h:306
static bool classof(const Value *V)
Definition: CoroInstr.h:238
static Function * getFunction(Constant *C)
Definition: Evaluator.cpp:220
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:1782
This represents the llvm.coro.size instruction.
Definition: CoroInstr.h:290
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1410
bool isFinal() const
Definition: CoroInstr.h:276
bool isPostSplit() const
Definition: CoroInstr.h:142
This is an important base class in LLVM.
Definition: Constant.h:41
ResumeKind getIndex() const
Definition: CoroInstr.h:48
Value * getMem() const
Definition: CoroInstr.h:220
static bool classof(const Value *V)
Definition: CoroInstr.h:63
This represents the llvm.coro.end instruction.
Definition: CoroInstr.h:302
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
bool isFromPromise() const
Definition: CoroInstr.h:248
This represents the llvm.coro.save instruction.
Definition: CoroInstr.h:232
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:107
static bool classof(const Value *V)
Definition: CoroInstr.h:296
static bool classof(const Value *V)
Definition: CoroInstr.h:192
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs, and aliases.
Definition: Value.cpp:529
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:219
This represents the llvm.coro.free instruction.
Definition: CoroInstr.h:198
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:256
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
Definition: IntrinsicInst.h:50
static bool classof(const Value *V)
Definition: CoroInstr.h:284
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
static bool classof(const Value *V)
Definition: CoroInstr.h:75
bool hasOutlinedParts() const
Definition: CoroInstr.h:141
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:214
ConstantArray - Constant Array Declarations.
Definition: Constants.h:413
ConstantArray * Resumers
Definition: CoroInstr.h:139
bool isUnwind() const
Definition: CoroInstr.h:307
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:205
void clearPromise()
Definition: CoroInstr.h:107
iv users
Definition: IVUsers.cpp:51
Value * getFrame() const
Definition: CoroInstr.h:202
static bool classof(const Value *V)
Definition: CoroInstr.h:315
static bool classof(const Value *V)
Definition: CoroInstr.h:208
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:293
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:281
static bool classof(const Value *V)
Definition: CoroInstr.h:180
#define I(x, y, z)
Definition: MD5.cpp:58
Function * getCoroutine() const
Definition: CoroInstr.h:165
static bool classof(const IntrinsicInst *I)
Definition: CoroInstr.h:72
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:322
Value * getFrame() const
Definition: CoroInstr.h:47
CoroIdInst * getId() const
Definition: CoroInstr.h:218
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This represents the llvm.coro.frame instruction.
Definition: CoroInstr.h:186
LLVM Value Representation.
Definition: Value.h:72
void setInfo(Constant *C)
Definition: CoroInstr.h:163
CoroAllocInst * getCoroAlloc()
Definition: CoroInstr.h:85
static bool classof(const Value *V)
Definition: CoroInstr.h:259
CoroSaveInst * getCoroSave() const
Definition: CoroInstr.h:269
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:43
an instruction to allocate memory on the stack
Definition: Instructions.h:59
Constant * getRawInfo() const
Definition: CoroInstr.h:159