LLVM 18.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,
64 MDTuple *TyMD = MDNode::get(F->getContext(), CM);
65 MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD);
67 Args.push_back(Arg2);
68 Args.push_back(VMD);
69 for (auto *Imm : Imms)
70 Args.push_back(Imm);
71 return IRB->CreateIntrinsic(IntrID, {Types}, Args);
72 }
73 void replaceMemInstrUses(Instruction *Old, Instruction *New);
74 void processInstrAfterVisit(Instruction *I);
75 void insertAssignPtrTypeIntrs(Instruction *I);
76 void insertAssignTypeIntrs(Instruction *I);
77 void processGlobalValue(GlobalVariable &GV);
78
79public:
80 static char ID;
81 SPIRVEmitIntrinsics() : FunctionPass(ID) {
83 }
84 SPIRVEmitIntrinsics(SPIRVTargetMachine *_TM) : FunctionPass(ID), TM(_TM) {
86 }
100 bool runOnFunction(Function &F) override;
101};
102} // namespace
103
104char SPIRVEmitIntrinsics::ID = 0;
105
106INITIALIZE_PASS(SPIRVEmitIntrinsics, "emit-intrinsics", "SPIRV emit intrinsics",
107 false, false)
108
109static inline bool isAssignTypeInstr(const Instruction *I) {
110 return isa<IntrinsicInst>(I) &&
111 cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::spv_assign_type;
112}
113
115 return isa<StoreInst>(I) || isa<LoadInst>(I) || isa<InsertValueInst>(I) ||
116 isa<ExtractValueInst>(I) || isa<AtomicCmpXchgInst>(I);
117}
118
119static bool isAggrToReplace(const Value *V) {
120 return isa<ConstantAggregate>(V) || isa<ConstantDataArray>(V) ||
121 (isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy());
122}
123
125 if (isa<PHINode>(I))
126 B.SetInsertPoint(I->getParent(), I->getParent()->getFirstInsertionPt());
127 else
128 B.SetInsertPoint(I);
129}
130
132 if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I))
133 return true;
134
135 return false;
136}
137
139 IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
140 if (Intr) {
141 switch (Intr->getIntrinsicID()) {
142 case Intrinsic::invariant_start:
143 case Intrinsic::invariant_end:
144 return false;
145 }
146 }
147 return true;
148}
149
150void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
151 Instruction *New) {
152 while (!Old->user_empty()) {
153 auto *U = Old->user_back();
154 if (isAssignTypeInstr(U)) {
155 IRB->SetInsertPoint(U);
156 SmallVector<Value *, 2> Args = {New, U->getOperand(1)};
157 IRB->CreateIntrinsic(Intrinsic::spv_assign_type, {New->getType()}, Args);
158 U->eraseFromParent();
159 } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) ||
160 isa<CallInst>(U)) {
161 U->replaceUsesOfWith(Old, New);
162 } else {
163 llvm_unreachable("illegal aggregate intrinsic user");
164 }
165 }
166 Old->eraseFromParent();
167}
168
169void SPIRVEmitIntrinsics::preprocessUndefs() {
170 std::queue<Instruction *> Worklist;
171 for (auto &I : instructions(F))
172 Worklist.push(&I);
173
174 while (!Worklist.empty()) {
175 Instruction *I = Worklist.front();
176 Worklist.pop();
177
178 for (auto &Op : I->operands()) {
179 auto *AggrUndef = dyn_cast<UndefValue>(Op);
180 if (!AggrUndef || !Op->getType()->isAggregateType())
181 continue;
182
183 IRB->SetInsertPoint(I);
184 auto *IntrUndef = IRB->CreateIntrinsic(Intrinsic::spv_undef, {}, {});
185 Worklist.push(IntrUndef);
186 I->replaceUsesOfWith(Op, IntrUndef);
187 AggrConsts[IntrUndef] = AggrUndef;
188 }
189 }
190}
191
192void SPIRVEmitIntrinsics::preprocessCompositeConstants() {
193 std::queue<Instruction *> Worklist;
194 for (auto &I : instructions(F))
195 Worklist.push(&I);
196
197 while (!Worklist.empty()) {
198 auto *I = Worklist.front();
199 assert(I);
200 bool KeepInst = false;
201 for (const auto &Op : I->operands()) {
202 auto BuildCompositeIntrinsic = [&KeepInst, &Worklist, &I, &Op,
203 this](Constant *AggrC,
205 IRB->SetInsertPoint(I);
206 auto *CCI =
207 IRB->CreateIntrinsic(Intrinsic::spv_const_composite, {}, {Args});
208 Worklist.push(CCI);
209 I->replaceUsesOfWith(Op, CCI);
210 KeepInst = true;
211 AggrConsts[CCI] = AggrC;
212 };
213
214 if (auto *AggrC = dyn_cast<ConstantAggregate>(Op)) {
215 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end());
216 BuildCompositeIntrinsic(AggrC, Args);
217 } else if (auto *AggrC = dyn_cast<ConstantDataArray>(Op)) {
219 for (unsigned i = 0; i < AggrC->getNumElements(); ++i)
220 Args.push_back(AggrC->getElementAsConstant(i));
221 BuildCompositeIntrinsic(AggrC, Args);
222 } else if (isa<ConstantAggregateZero>(Op) &&
223 !Op->getType()->isVectorTy()) {
224 auto *AggrC = cast<ConstantAggregateZero>(Op);
225 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end());
226 BuildCompositeIntrinsic(AggrC, Args);
227 }
228 }
229 if (!KeepInst)
230 Worklist.pop();
231 }
232}
233
234Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
236 for (auto &Op : I.operands())
237 if (Op.get()->getType()->isSized())
238 Args.push_back(Op);
239 IRB->SetInsertPoint(&I);
240 IRB->CreateIntrinsic(Intrinsic::spv_switch, {I.getOperand(0)->getType()},
241 {Args});
242 return &I;
243}
244
245Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
246 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
248 Args.push_back(IRB->getInt1(I.isInBounds()));
249 for (auto &Op : I.operands())
250 Args.push_back(Op);
251 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
252 I.replaceAllUsesWith(NewI);
253 I.eraseFromParent();
254 return NewI;
255}
256
257Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
258 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
259 SmallVector<Value *> Args(I.op_begin(), I.op_end());
260 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args});
261 std::string InstName = I.hasName() ? I.getName().str() : "";
262 I.replaceAllUsesWith(NewI);
263 I.eraseFromParent();
264 NewI->setName(InstName);
265 return NewI;
266}
267
268Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
269 SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
270 I.getOperand(1)->getType(),
271 I.getOperand(2)->getType()};
272 SmallVector<Value *> Args(I.op_begin(), I.op_end());
273 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
274 std::string InstName = I.hasName() ? I.getName().str() : "";
275 I.replaceAllUsesWith(NewI);
276 I.eraseFromParent();
277 NewI->setName(InstName);
278 return NewI;
279}
280
282SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
283 SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
284 I.getIndexOperand()->getType()};
285 SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()};
286 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
287 std::string InstName = I.hasName() ? I.getName().str() : "";
288 I.replaceAllUsesWith(NewI);
289 I.eraseFromParent();
290 NewI->setName(InstName);
291 return NewI;
292}
293
294Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
295 SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()};
297 for (auto &Op : I.operands())
298 if (isa<UndefValue>(Op))
299 Args.push_back(UndefValue::get(IRB->getInt32Ty()));
300 else
301 Args.push_back(Op);
302 for (auto &Op : I.indices())
303 Args.push_back(IRB->getInt32(Op));
304 Instruction *NewI =
305 IRB->CreateIntrinsic(Intrinsic::spv_insertv, {Types}, {Args});
306 replaceMemInstrUses(&I, NewI);
307 return NewI;
308}
309
310Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
312 for (auto &Op : I.operands())
313 Args.push_back(Op);
314 for (auto &Op : I.indices())
315 Args.push_back(IRB->getInt32(Op));
316 auto *NewI =
317 IRB->CreateIntrinsic(Intrinsic::spv_extractv, {I.getType()}, {Args});
318 I.replaceAllUsesWith(NewI);
319 I.eraseFromParent();
320 return NewI;
321}
322
323Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) {
324 if (!I.getType()->isAggregateType())
325 return &I;
326 TrackConstants = false;
327 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
329 TLI->getLoadMemOperandFlags(I, F->getParent()->getDataLayout());
330 auto *NewI =
331 IRB->CreateIntrinsic(Intrinsic::spv_load, {I.getOperand(0)->getType()},
332 {I.getPointerOperand(), IRB->getInt16(Flags),
333 IRB->getInt8(I.getAlign().value())});
334 replaceMemInstrUses(&I, NewI);
335 return NewI;
336}
337
338Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
339 if (!AggrStores.contains(&I))
340 return &I;
341 TrackConstants = false;
342 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
344 TLI->getStoreMemOperandFlags(I, F->getParent()->getDataLayout());
345 auto *PtrOp = I.getPointerOperand();
346 auto *NewI = IRB->CreateIntrinsic(
347 Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
348 {I.getValueOperand(), PtrOp, IRB->getInt16(Flags),
349 IRB->getInt8(I.getAlign().value())});
350 I.eraseFromParent();
351 return NewI;
352}
353
354Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) {
355 TrackConstants = false;
356 Type *PtrTy = I.getType();
357 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {});
358 std::string InstName = I.hasName() ? I.getName().str() : "";
359 I.replaceAllUsesWith(NewI);
360 I.eraseFromParent();
361 NewI->setName(InstName);
362 return NewI;
363}
364
365Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
366 assert(I.getType()->isAggregateType() && "Aggregate result is expected");
368 for (auto &Op : I.operands())
369 Args.push_back(Op);
370 Args.push_back(IRB->getInt32(I.getSyncScopeID()));
371 Args.push_back(IRB->getInt32(
372 static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering()))));
373 Args.push_back(IRB->getInt32(
374 static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering()))));
375 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_cmpxchg,
376 {I.getPointerOperand()->getType()}, {Args});
377 replaceMemInstrUses(&I, NewI);
378 return NewI;
379}
380
381Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
382 IRB->SetInsertPoint(&I);
383 IRB->CreateIntrinsic(Intrinsic::spv_unreachable, {}, {});
384 return &I;
385}
386
387void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV) {
388 // Skip special artifical variable llvm.global.annotations.
389 if (GV.getName() == "llvm.global.annotations")
390 return;
391 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
393 Type *Ty = isAggrToReplace(Init) ? IRB->getInt32Ty() : Init->getType();
395 auto *InitInst = IRB->CreateIntrinsic(Intrinsic::spv_init_global,
396 {GV.getType(), Ty}, {&GV, Const});
397 InitInst->setArgOperand(1, Init);
398 }
399 if ((!GV.hasInitializer() || isa<UndefValue>(GV.getInitializer())) &&
400 GV.getNumUses() == 0)
401 IRB->CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV);
402}
403
404void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) {
405 if (I->getType()->isVoidTy() || !requireAssignPtrType(I))
406 return;
407
408 setInsertPointSkippingPhis(*IRB, I->getNextNode());
409
410 Constant *EltTyConst;
411 unsigned AddressSpace = 0;
412 if (auto *AI = dyn_cast<AllocaInst>(I)) {
413 EltTyConst = Constant::getNullValue(AI->getAllocatedType());
414 AddressSpace = AI->getAddressSpace();
415 } else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
416 EltTyConst = Constant::getNullValue(GEP->getResultElementType());
417 AddressSpace = GEP->getPointerAddressSpace();
418 } else {
419 llvm_unreachable("Unexpected instruction!");
420 }
421
422 buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I,
423 {IRB->getInt32(AddressSpace)});
424}
425
426void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
427 Type *Ty = I->getType();
428 if (!Ty->isVoidTy() && requireAssignType(I) && !requireAssignPtrType(I)) {
429 setInsertPointSkippingPhis(*IRB, I->getNextNode());
430 Type *TypeToAssign = Ty;
431 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
432 if (II->getIntrinsicID() == Intrinsic::spv_const_composite ||
433 II->getIntrinsicID() == Intrinsic::spv_undef) {
434 auto t = AggrConsts.find(II);
435 assert(t != AggrConsts.end());
436 TypeToAssign = t->second->getType();
437 }
438 }
439 Constant *Const = Constant::getNullValue(TypeToAssign);
440 buildIntrWithMD(Intrinsic::spv_assign_type, {Ty}, Const, I, {});
441 }
442 for (const auto &Op : I->operands()) {
443 if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
444 // Check GetElementPtrConstantExpr case.
445 (isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
447 if (isa<UndefValue>(Op) && Op->getType()->isAggregateType())
448 buildIntrWithMD(Intrinsic::spv_assign_type, {IRB->getInt32Ty()}, Op,
449 UndefValue::get(IRB->getInt32Ty()), {});
450 else
451 buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op,
452 {});
453 }
454 }
455}
456
457void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I) {
458 auto *II = dyn_cast<IntrinsicInst>(I);
459 if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite &&
460 TrackConstants) {
461 IRB->SetInsertPoint(I->getNextNode());
462 Type *Ty = IRB->getInt32Ty();
463 auto t = AggrConsts.find(I);
464 assert(t != AggrConsts.end());
465 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant, {Ty, Ty},
466 t->second, I, {});
467 I->replaceAllUsesWith(NewOp);
468 NewOp->setArgOperand(0, I);
469 }
470 for (const auto &Op : I->operands()) {
471 if ((isa<ConstantAggregateZero>(Op) && Op->getType()->isVectorTy()) ||
472 isa<PHINode>(I) || isa<SwitchInst>(I))
473 TrackConstants = false;
474 if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
475 unsigned OpNo = Op.getOperandNo();
476 if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
477 (II->paramHasAttr(OpNo, Attribute::ImmArg))))
478 continue;
479 IRB->SetInsertPoint(I);
480 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
481 {Op->getType(), Op->getType()}, Op, Op, {});
482 I->setOperand(OpNo, NewOp);
483 }
484 }
485 if (I->hasName()) {
486 setInsertPointSkippingPhis(*IRB, I->getNextNode());
487 std::vector<Value *> Args = {I};
488 addStringImm(I->getName(), *IRB, Args);
489 IRB->CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
490 }
491}
492
493bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
494 if (Func.isDeclaration())
495 return false;
496 F = &Func;
497 IRB = new IRBuilder<>(Func.getContext());
498 AggrConsts.clear();
499 AggrStores.clear();
500
501 // StoreInst's operand type can be changed during the next transformations,
502 // so we need to store it in the set. Also store already transformed types.
503 for (auto &I : instructions(Func)) {
504 StoreInst *SI = dyn_cast<StoreInst>(&I);
505 if (!SI)
506 continue;
507 Type *ElTy = SI->getValueOperand()->getType();
508 PointerType *PTy = cast<PointerType>(SI->getOperand(1)->getType());
509 if (ElTy->isAggregateType() || ElTy->isVectorTy() ||
510 !PTy->isOpaqueOrPointeeTypeMatches(ElTy))
511 AggrStores.insert(&I);
512 }
513
514 IRB->SetInsertPoint(&Func.getEntryBlock(), Func.getEntryBlock().begin());
515 for (auto &GV : Func.getParent()->globals())
516 processGlobalValue(GV);
517
518 preprocessUndefs();
519 preprocessCompositeConstants();
521 for (auto &I : instructions(Func))
522 Worklist.push_back(&I);
523
524 for (auto &I : Worklist) {
525 insertAssignPtrTypeIntrs(I);
526 insertAssignTypeIntrs(I);
527 }
528
529 for (auto *I : Worklist) {
530 TrackConstants = true;
531 if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
532 IRB->SetInsertPoint(I->getNextNode());
533 I = visit(*I);
534 processInstrAfterVisit(I);
535 }
536 return true;
537}
538
540 return new SPIRVEmitIntrinsics(TM);
541}
aarch64 promote const
unsigned Intr
always inline
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Hexagon Common GEP
Select target instructions out of generic instructions
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isMemInstrToReplace(Instruction *I)
static bool isAggrToReplace(const Value *V)
static bool requireAssignPtrType(Instruction *I)
static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I)
static bool requireAssignType(Instruction *I)
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
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:1362
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
This class represents an Operation in the Expression.
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:311
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:941
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:2628
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:83
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:1416
Tuple of metadata.
Definition: Metadata.h:1345
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:37
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:265
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition: Type.h:295
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:1724
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:378
unsigned getNumUses() const
This method computes the number of uses of this Value.
Definition: Value.cpp:255
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
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
NodeAddr< FuncNode * > Func
Definition: RDFGraph.h:393
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeSPIRVEmitIntrinsicsPass(PassRegistry &)
AddressSpace
Definition: NVPTXBaseInfo.h:21
FunctionPass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
DWARFExpression::Operation Op
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:50
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
Definition: SPIRVUtils.cpp:192