LLVM 17.0.0git
SPIRVEmitIntrinsics.cpp
Go to the documentation of this file.
1//===-- SPIRVEmitIntrinsics.cpp - emit SPIRV intrinsics ---------*- 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//
9// The pass emits SPIRV intrinsics keeping essential high-level information for
10// the translation of LLVM IR to SPIR-V.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "SPIRVTargetMachine.h"
16#include "SPIRVUtils.h"
17#include "llvm/IR/IRBuilder.h"
19#include "llvm/IR/InstVisitor.h"
20#include "llvm/IR/IntrinsicsSPIRV.h"
21
22#include <queue>
23
24// This pass performs the following transformation on LLVM IR level required
25// for the following translation to SPIR-V:
26// - replaces direct usages of aggregate constants with target-specific
27// intrinsics;
28// - replaces aggregates-related instructions (extract/insert, ld/st, etc)
29// with a target-specific intrinsics;
30// - emits intrinsics for the global variable initializers since IRTranslator
31// doesn't handle them and it's not very convenient to translate them
32// ourselves;
33// - emits intrinsics to keep track of the string names assigned to the values;
34// - emits intrinsics to keep track of constants (this is necessary to have an
35// LLVM IR constant after the IRTranslation is completed) for their further
36// deduplication;
37// - emits intrinsics to keep track of original LLVM types of the values
38// to be able to emit proper SPIR-V types eventually.
39//
40// TODO: consider removing spv.track.constant in favor of spv.assign.type.
41
42using namespace llvm;
43
44namespace llvm {
46} // namespace llvm
47
48namespace {
49class SPIRVEmitIntrinsics
50 : public FunctionPass,
51 public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
52 SPIRVTargetMachine *TM = nullptr;
53 IRBuilder<> *IRB = nullptr;
54 Function *F = nullptr;
55 bool TrackConstants = true;
57 DenseSet<Instruction *> AggrStores;
58 void preprocessCompositeConstants();
59 void preprocessUndefs();
60 CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
61 Value *Arg, Value *Arg2) {
63 MDTuple *TyMD = MDNode::get(F->getContext(), CM);
64 MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD);
65 return IRB->CreateIntrinsic(IntrID, {Types}, {Arg2, VMD});
66 }
67 void replaceMemInstrUses(Instruction *Old, Instruction *New);
68 void processInstrAfterVisit(Instruction *I);
69 void insertAssignTypeIntrs(Instruction *I);
70 void processGlobalValue(GlobalVariable &GV);
71
72public:
73 static char ID;
74 SPIRVEmitIntrinsics() : FunctionPass(ID) {
76 }
77 SPIRVEmitIntrinsics(SPIRVTargetMachine *_TM) : FunctionPass(ID), TM(_TM) {
79 }
93 bool runOnFunction(Function &F) override;
94};
95} // namespace
96
97char SPIRVEmitIntrinsics::ID = 0;
98
99INITIALIZE_PASS(SPIRVEmitIntrinsics, "emit-intrinsics", "SPIRV emit intrinsics",
100 false, false)
101
102static inline bool isAssignTypeInstr(const Instruction *I) {
103 return isa<IntrinsicInst>(I) &&
104 cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::spv_assign_type;
105}
106
108 return isa<StoreInst>(I) || isa<LoadInst>(I) || isa<InsertValueInst>(I) ||
109 isa<ExtractValueInst>(I) || isa<AtomicCmpXchgInst>(I);
110}
111
112static bool isAggrToReplace(const Value *V) {
113 return isa<ConstantAggregate>(V) || isa<ConstantDataArray>(V) ||
114 (isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy());
115}
116
118 if (isa<PHINode>(I))
119 B.SetInsertPoint(I->getParent(), I->getParent()->getFirstInsertionPt());
120 else
121 B.SetInsertPoint(I);
122}
123
125 IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
126 if (Intr) {
127 switch (Intr->getIntrinsicID()) {
128 case Intrinsic::invariant_start:
129 case Intrinsic::invariant_end:
130 return false;
131 }
132 }
133 return true;
134}
135
136void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
137 Instruction *New) {
138 while (!Old->user_empty()) {
139 auto *U = Old->user_back();
140 if (isAssignTypeInstr(U)) {
141 IRB->SetInsertPoint(U);
142 SmallVector<Value *, 2> Args = {New, U->getOperand(1)};
143 IRB->CreateIntrinsic(Intrinsic::spv_assign_type, {New->getType()}, Args);
144 U->eraseFromParent();
145 } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) ||
146 isa<CallInst>(U)) {
147 U->replaceUsesOfWith(Old, New);
148 } else {
149 llvm_unreachable("illegal aggregate intrinsic user");
150 }
151 }
152 Old->eraseFromParent();
153}
154
155void SPIRVEmitIntrinsics::preprocessUndefs() {
156 std::queue<Instruction *> Worklist;
157 for (auto &I : instructions(F))
158 Worklist.push(&I);
159
160 while (!Worklist.empty()) {
161 Instruction *I = Worklist.front();
162 Worklist.pop();
163
164 for (auto &Op : I->operands()) {
165 auto *AggrUndef = dyn_cast<UndefValue>(Op);
166 if (!AggrUndef || !Op->getType()->isAggregateType())
167 continue;
168
169 IRB->SetInsertPoint(I);
170 auto *IntrUndef = IRB->CreateIntrinsic(Intrinsic::spv_undef, {}, {});
171 Worklist.push(IntrUndef);
172 I->replaceUsesOfWith(Op, IntrUndef);
173 AggrConsts[IntrUndef] = AggrUndef;
174 }
175 }
176}
177
178void SPIRVEmitIntrinsics::preprocessCompositeConstants() {
179 std::queue<Instruction *> Worklist;
180 for (auto &I : instructions(F))
181 Worklist.push(&I);
182
183 while (!Worklist.empty()) {
184 auto *I = Worklist.front();
185 assert(I);
186 bool KeepInst = false;
187 for (const auto &Op : I->operands()) {
188 auto BuildCompositeIntrinsic = [&KeepInst, &Worklist, &I, &Op,
189 this](Constant *AggrC,
191 IRB->SetInsertPoint(I);
192 auto *CCI =
193 IRB->CreateIntrinsic(Intrinsic::spv_const_composite, {}, {Args});
194 Worklist.push(CCI);
195 I->replaceUsesOfWith(Op, CCI);
196 KeepInst = true;
197 AggrConsts[CCI] = AggrC;
198 };
199
200 if (auto *AggrC = dyn_cast<ConstantAggregate>(Op)) {
201 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end());
202 BuildCompositeIntrinsic(AggrC, Args);
203 } else if (auto *AggrC = dyn_cast<ConstantDataArray>(Op)) {
205 for (unsigned i = 0; i < AggrC->getNumElements(); ++i)
206 Args.push_back(AggrC->getElementAsConstant(i));
207 BuildCompositeIntrinsic(AggrC, Args);
208 } else if (isa<ConstantAggregateZero>(Op) &&
209 !Op->getType()->isVectorTy()) {
210 auto *AggrC = cast<ConstantAggregateZero>(Op);
211 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end());
212 BuildCompositeIntrinsic(AggrC, Args);
213 }
214 }
215 if (!KeepInst)
216 Worklist.pop();
217 }
218}
219
220Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
222 for (auto &Op : I.operands())
223 if (Op.get()->getType()->isSized())
224 Args.push_back(Op);
225 IRB->SetInsertPoint(&I);
226 IRB->CreateIntrinsic(Intrinsic::spv_switch, {I.getOperand(0)->getType()},
227 {Args});
228 return &I;
229}
230
231Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
232 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
234 Args.push_back(IRB->getInt1(I.isInBounds()));
235 for (auto &Op : I.operands())
236 Args.push_back(Op);
237 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
238 I.replaceAllUsesWith(NewI);
239 I.eraseFromParent();
240 return NewI;
241}
242
243Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
244 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
245 SmallVector<Value *> Args(I.op_begin(), I.op_end());
246 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args});
247 std::string InstName = I.hasName() ? I.getName().str() : "";
248 I.replaceAllUsesWith(NewI);
249 I.eraseFromParent();
250 NewI->setName(InstName);
251 return NewI;
252}
253
254Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
255 SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
256 I.getOperand(1)->getType(),
257 I.getOperand(2)->getType()};
258 SmallVector<Value *> Args(I.op_begin(), I.op_end());
259 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
260 std::string InstName = I.hasName() ? I.getName().str() : "";
261 I.replaceAllUsesWith(NewI);
262 I.eraseFromParent();
263 NewI->setName(InstName);
264 return NewI;
265}
266
268SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
269 SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
270 I.getIndexOperand()->getType()};
271 SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()};
272 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
273 std::string InstName = I.hasName() ? I.getName().str() : "";
274 I.replaceAllUsesWith(NewI);
275 I.eraseFromParent();
276 NewI->setName(InstName);
277 return NewI;
278}
279
280Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
281 SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()};
283 for (auto &Op : I.operands())
284 if (isa<UndefValue>(Op))
285 Args.push_back(UndefValue::get(IRB->getInt32Ty()));
286 else
287 Args.push_back(Op);
288 for (auto &Op : I.indices())
289 Args.push_back(IRB->getInt32(Op));
290 Instruction *NewI =
291 IRB->CreateIntrinsic(Intrinsic::spv_insertv, {Types}, {Args});
292 replaceMemInstrUses(&I, NewI);
293 return NewI;
294}
295
296Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
298 for (auto &Op : I.operands())
299 Args.push_back(Op);
300 for (auto &Op : I.indices())
301 Args.push_back(IRB->getInt32(Op));
302 auto *NewI =
303 IRB->CreateIntrinsic(Intrinsic::spv_extractv, {I.getType()}, {Args});
304 I.replaceAllUsesWith(NewI);
305 I.eraseFromParent();
306 return NewI;
307}
308
309Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) {
310 if (!I.getType()->isAggregateType())
311 return &I;
312 TrackConstants = false;
313 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
315 TLI->getLoadMemOperandFlags(I, F->getParent()->getDataLayout());
316 auto *NewI =
317 IRB->CreateIntrinsic(Intrinsic::spv_load, {I.getOperand(0)->getType()},
318 {I.getPointerOperand(), IRB->getInt16(Flags),
319 IRB->getInt8(I.getAlign().value())});
320 replaceMemInstrUses(&I, NewI);
321 return NewI;
322}
323
324Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
325 if (!AggrStores.contains(&I))
326 return &I;
327 TrackConstants = false;
328 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
330 TLI->getStoreMemOperandFlags(I, F->getParent()->getDataLayout());
331 auto *PtrOp = I.getPointerOperand();
332 auto *NewI = IRB->CreateIntrinsic(
333 Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
334 {I.getValueOperand(), PtrOp, IRB->getInt16(Flags),
335 IRB->getInt8(I.getAlign().value())});
336 I.eraseFromParent();
337 return NewI;
338}
339
340Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) {
341 TrackConstants = false;
342 Type *PtrTy = I.getType();
343 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {});
344 std::string InstName = I.hasName() ? I.getName().str() : "";
345 I.replaceAllUsesWith(NewI);
346 I.eraseFromParent();
347 NewI->setName(InstName);
348 return NewI;
349}
350
351Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
352 assert(I.getType()->isAggregateType() && "Aggregate result is expected");
354 for (auto &Op : I.operands())
355 Args.push_back(Op);
356 Args.push_back(IRB->getInt32(I.getSyncScopeID()));
357 Args.push_back(IRB->getInt32(
358 static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering()))));
359 Args.push_back(IRB->getInt32(
360 static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering()))));
361 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_cmpxchg,
362 {I.getPointerOperand()->getType()}, {Args});
363 replaceMemInstrUses(&I, NewI);
364 return NewI;
365}
366
367Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
368 IRB->SetInsertPoint(&I);
369 IRB->CreateIntrinsic(Intrinsic::spv_unreachable, {}, {});
370 return &I;
371}
372
373void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV) {
374 // Skip special artifical variable llvm.global.annotations.
375 if (GV.getName() == "llvm.global.annotations")
376 return;
377 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
379 Type *Ty = isAggrToReplace(Init) ? IRB->getInt32Ty() : Init->getType();
381 auto *InitInst = IRB->CreateIntrinsic(Intrinsic::spv_init_global,
382 {GV.getType(), Ty}, {&GV, Const});
383 InitInst->setArgOperand(1, Init);
384 }
385 if ((!GV.hasInitializer() || isa<UndefValue>(GV.getInitializer())) &&
386 GV.getNumUses() == 0)
387 IRB->CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV);
388}
389
390void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
391 Type *Ty = I->getType();
392 if (!Ty->isVoidTy() && requireAssignType(I)) {
393 setInsertPointSkippingPhis(*IRB, I->getNextNode());
394 Type *TypeToAssign = Ty;
395 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
396 if (II->getIntrinsicID() == Intrinsic::spv_const_composite ||
397 II->getIntrinsicID() == Intrinsic::spv_undef) {
398 auto t = AggrConsts.find(II);
399 assert(t != AggrConsts.end());
400 TypeToAssign = t->second->getType();
401 }
402 }
403 Constant *Const = Constant::getNullValue(TypeToAssign);
404 buildIntrWithMD(Intrinsic::spv_assign_type, {Ty}, Const, I);
405 }
406 for (const auto &Op : I->operands()) {
407 if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
408 // Check GetElementPtrConstantExpr case.
409 (isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
411 if (isa<UndefValue>(Op) && Op->getType()->isAggregateType())
412 buildIntrWithMD(Intrinsic::spv_assign_type, {IRB->getInt32Ty()}, Op,
414 else
415 buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op);
416 }
417 }
418}
419
420void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I) {
421 auto *II = dyn_cast<IntrinsicInst>(I);
422 if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite &&
423 TrackConstants) {
424 IRB->SetInsertPoint(I->getNextNode());
425 Type *Ty = IRB->getInt32Ty();
426 auto t = AggrConsts.find(I);
427 assert(t != AggrConsts.end());
428 auto *NewOp =
429 buildIntrWithMD(Intrinsic::spv_track_constant, {Ty, Ty}, t->second, I);
430 I->replaceAllUsesWith(NewOp);
431 NewOp->setArgOperand(0, I);
432 }
433 for (const auto &Op : I->operands()) {
434 if ((isa<ConstantAggregateZero>(Op) && Op->getType()->isVectorTy()) ||
435 isa<PHINode>(I) || isa<SwitchInst>(I))
436 TrackConstants = false;
437 if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
438 unsigned OpNo = Op.getOperandNo();
439 if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
440 (II->paramHasAttr(OpNo, Attribute::ImmArg))))
441 continue;
442 IRB->SetInsertPoint(I);
443 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
444 {Op->getType(), Op->getType()}, Op, Op);
445 I->setOperand(OpNo, NewOp);
446 }
447 }
448 if (I->hasName()) {
449 setInsertPointSkippingPhis(*IRB, I->getNextNode());
450 std::vector<Value *> Args = {I};
451 addStringImm(I->getName(), *IRB, Args);
452 IRB->CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
453 }
454}
455
456bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
457 if (Func.isDeclaration())
458 return false;
459 F = &Func;
460 IRB = new IRBuilder<>(Func.getContext());
461 AggrConsts.clear();
462 AggrStores.clear();
463
464 // StoreInst's operand type can be changed during the next transformations,
465 // so we need to store it in the set. Also store already transformed types.
466 for (auto &I : instructions(Func)) {
467 StoreInst *SI = dyn_cast<StoreInst>(&I);
468 if (!SI)
469 continue;
470 Type *ElTy = SI->getValueOperand()->getType();
471 PointerType *PTy = cast<PointerType>(SI->getOperand(1)->getType());
472 if (ElTy->isAggregateType() || ElTy->isVectorTy() ||
473 !PTy->isOpaqueOrPointeeTypeMatches(ElTy))
474 AggrStores.insert(&I);
475 }
476
477 IRB->SetInsertPoint(&Func.getEntryBlock().front());
478 for (auto &GV : Func.getParent()->globals())
479 processGlobalValue(GV);
480
481 preprocessUndefs();
482 preprocessCompositeConstants();
484 for (auto &I : instructions(Func))
485 Worklist.push_back(&I);
486
487 for (auto &I : Worklist)
488 insertAssignTypeIntrs(I);
489
490 for (auto *I : Worklist) {
491 TrackConstants = true;
492 if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
493 IRB->SetInsertPoint(I->getNextNode());
494 I = visit(*I);
495 processInstrAfterVisit(I);
496 }
497 return true;
498}
499
501 return new SPIRVEmitIntrinsics(TM);
502}
aarch64 promote const
unsigned Intr
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
always inline
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
print must be executed print the must be executed context for all instructions
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
@ SI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isMemInstrToReplace(Instruction *I)
static bool isAggrToReplace(const Value *V)
static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I)
static bool requireAssignType(Instruction *I)
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
@ Flags
Definition: TextStubV5.cpp:93
an instruction to allocate memory on the stack
Definition: Instructions.h:58
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:513
This class represents a no-op cast from one type to another.
void setArgOperand(unsigned i, Value *v)
Definition: InstrTypes.h:1358
This class represents a function call, abstracting a target machine's calling convention.
This is an important base class in LLVM.
Definition: Constant.h:41
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:356
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
iterator end()
Definition: DenseMap.h:84
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
This instruction extracts a single (scalar) element from a VectorType value.
This instruction extracts a struct member or array element value from an aggregate value.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:940
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:290
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
Definition: IRBuilder.h:447
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:975
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:512
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Definition: IRBuilder.h:462
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition: IRBuilder.h:472
ConstantInt * getInt16(uint16_t C)
Get a constant 16-bit value.
Definition: IRBuilder.h:467
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:180
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2558
This instruction inserts a single (scalar) element into a VectorType value.
This instruction inserts a struct field of array element value into an aggregate value.
Base class for instruction visitors.
Definition: InstVisitor.h:78
RetTy visitExtractElementInst(ExtractElementInst &I)
Definition: InstVisitor.h:191
RetTy visitInsertValueInst(InsertValueInst &I)
Definition: InstVisitor.h:195
RetTy visitUnreachableInst(UnreachableInst &I)
Definition: InstVisitor.h:241
RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I)
Definition: InstVisitor.h:171
RetTy visitBitCastInst(BitCastInst &I)
Definition: InstVisitor.h:187
RetTy visitSwitchInst(SwitchInst &I)
Definition: InstVisitor.h:232
RetTy visitExtractValueInst(ExtractValueInst &I)
Definition: InstVisitor.h:194
RetTy visitStoreInst(StoreInst &I)
Definition: InstVisitor.h:170
RetTy visitInsertElementInst(InsertElementInst &I)
Definition: InstVisitor.h:192
RetTy visitAllocaInst(AllocaInst &I)
Definition: InstVisitor.h:168
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
Definition: InstVisitor.h:174
void visitInstruction(Instruction &I)
Definition: InstVisitor.h:280
RetTy visitLoadInst(LoadInst &I)
Definition: InstVisitor.h:169
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
Definition: Instruction.h:87
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:82
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:47
An instruction for reading from memory.
Definition: Instructions.h:177
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1399
Tuple of metadata.
Definition: Metadata.h:1328
Flags
Flags values. These may be or'd together.
Metadata wrapper in the Value hierarchy.
Definition: Metadata.h:175
static MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition: Metadata.cpp:102
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
An instruction for storing to memory.
Definition: Instructions.h:301
Multiway switch.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:267
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition: Type.h:297
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1739
This function has undefined behavior.
static ConstantAsMetadata * getConstant(Value *C)
Definition: Metadata.h:366
LLVM Value Representation.
Definition: Value.h:74
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:375
unsigned getNumUses() const
This method computes the number of uses of this Value.
Definition: Value.cpp:254
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:308
bool user_empty() const
Definition: Value.h:385
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition: DenseSet.h:185
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeSPIRVEmitIntrinsicsPass(PassRegistry &)
FunctionPass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:49
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
Definition: SPIRVUtils.cpp:191