LLVM 19.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 "SPIRVBuiltins.h"
16#include "SPIRVMetadata.h"
17#include "SPIRVSubtarget.h"
18#include "SPIRVTargetMachine.h"
19#include "SPIRVUtils.h"
20#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/InstVisitor.h"
23#include "llvm/IR/IntrinsicsSPIRV.h"
25
26#include <queue>
27
28// This pass performs the following transformation on LLVM IR level required
29// for the following translation to SPIR-V:
30// - replaces direct usages of aggregate constants with target-specific
31// intrinsics;
32// - replaces aggregates-related instructions (extract/insert, ld/st, etc)
33// with a target-specific intrinsics;
34// - emits intrinsics for the global variable initializers since IRTranslator
35// doesn't handle them and it's not very convenient to translate them
36// ourselves;
37// - emits intrinsics to keep track of the string names assigned to the values;
38// - emits intrinsics to keep track of constants (this is necessary to have an
39// LLVM IR constant after the IRTranslation is completed) for their further
40// deduplication;
41// - emits intrinsics to keep track of original LLVM types of the values
42// to be able to emit proper SPIR-V types eventually.
43//
44// TODO: consider removing spv.track.constant in favor of spv.assign.type.
45
46using namespace llvm;
47
48namespace llvm {
50} // namespace llvm
51
52namespace {
53
54inline MetadataAsValue *buildMD(Value *Arg) {
55 LLVMContext &Ctx = Arg->getContext();
58}
59
60class SPIRVEmitIntrinsics
61 : public ModulePass,
62 public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
63 SPIRVTargetMachine *TM = nullptr;
64 SPIRVGlobalRegistry *GR = nullptr;
65 Function *F = nullptr;
66 bool TrackConstants = true;
69 DenseSet<Instruction *> AggrStores;
70
71 // deduce element type of untyped pointers
72 Type *deduceElementType(Value *I, bool UnknownElemTypeI8);
73 Type *deduceElementTypeHelper(Value *I);
74 Type *deduceElementTypeHelper(Value *I, std::unordered_set<Value *> &Visited);
75 Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
76 std::unordered_set<Value *> &Visited);
77 Type *deduceElementTypeByUsersDeep(Value *Op,
78 std::unordered_set<Value *> &Visited);
79
80 // deduce nested types of composites
81 Type *deduceNestedTypeHelper(User *U);
82 Type *deduceNestedTypeHelper(User *U, Type *Ty,
83 std::unordered_set<Value *> &Visited);
84
85 // deduce Types of operands of the Instruction if possible
86 void deduceOperandElementType(Instruction *I);
87
88 void preprocessCompositeConstants(IRBuilder<> &B);
89 void preprocessUndefs(IRBuilder<> &B);
90
91 CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
92 Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
93 IRBuilder<> &B) {
95 Args.push_back(Arg2);
96 Args.push_back(buildMD(Arg));
97 for (auto *Imm : Imms)
98 Args.push_back(Imm);
99 return B.CreateIntrinsic(IntrID, {Types}, Args);
100 }
101
102 void buildAssignType(IRBuilder<> &B, Type *ElemTy, Value *Arg);
103 void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg);
104 void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType);
105
106 void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B);
107 void processInstrAfterVisit(Instruction *I, IRBuilder<> &B);
108 bool insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B,
109 bool UnknownElemTypeI8);
110 void insertAssignTypeIntrs(Instruction *I, IRBuilder<> &B);
111 void insertAssignPtrTypeTargetExt(TargetExtType *AssignedType, Value *V,
112 IRBuilder<> &B);
113 void replacePointerOperandWithPtrCast(Instruction *I, Value *Pointer,
114 Type *ExpectedElementType,
115 unsigned OperandToReplace,
116 IRBuilder<> &B);
117 void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B);
119 void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B);
120 void processParamTypes(Function *F, IRBuilder<> &B);
121 void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
122 Type *deduceFunParamElementType(Function *F, unsigned OpIdx);
123 Type *deduceFunParamElementType(Function *F, unsigned OpIdx,
124 std::unordered_set<Function *> &FVisited);
125
126public:
127 static char ID;
128 SPIRVEmitIntrinsics() : ModulePass(ID) {
130 }
131 SPIRVEmitIntrinsics(SPIRVTargetMachine *_TM) : ModulePass(ID), TM(_TM) {
133 }
148
149 StringRef getPassName() const override { return "SPIRV emit intrinsics"; }
150
151 bool runOnModule(Module &M) override;
152 bool runOnFunction(Function &F);
153
154 void getAnalysisUsage(AnalysisUsage &AU) const override {
156 }
157};
158
159bool isConvergenceIntrinsic(const Instruction *I) {
160 const auto *II = dyn_cast<IntrinsicInst>(I);
161 if (!II)
162 return false;
163
164 return II->getIntrinsicID() == Intrinsic::experimental_convergence_entry ||
165 II->getIntrinsicID() == Intrinsic::experimental_convergence_loop ||
166 II->getIntrinsicID() == Intrinsic::experimental_convergence_anchor;
167}
168} // namespace
169
170char SPIRVEmitIntrinsics::ID = 0;
171
172INITIALIZE_PASS(SPIRVEmitIntrinsics, "emit-intrinsics", "SPIRV emit intrinsics",
173 false, false)
174
175static inline bool isAssignTypeInstr(const Instruction *I) {
176 return isa<IntrinsicInst>(I) &&
177 cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::spv_assign_type;
178}
179
181 return isa<StoreInst>(I) || isa<LoadInst>(I) || isa<InsertValueInst>(I) ||
182 isa<ExtractValueInst>(I) || isa<AtomicCmpXchgInst>(I);
183}
184
185static bool isAggrConstForceInt32(const Value *V) {
186 return isa<ConstantArray>(V) || isa<ConstantStruct>(V) ||
187 isa<ConstantDataArray>(V) ||
188 (isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy());
189}
190
192 if (isa<PHINode>(I))
193 B.SetInsertPoint(I->getParent()->getFirstNonPHIOrDbgOrAlloca());
194 else
195 B.SetInsertPoint(I);
196}
197
199 B.SetCurrentDebugLocation(I->getDebugLoc());
200 if (I->getType()->isVoidTy())
201 B.SetInsertPoint(I->getNextNode());
202 else
203 B.SetInsertPoint(*I->getInsertionPointAfterDef());
204}
205
207 IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
208 if (Intr) {
209 switch (Intr->getIntrinsicID()) {
210 case Intrinsic::invariant_start:
211 case Intrinsic::invariant_end:
212 return false;
213 }
214 }
215 return true;
216}
217
218static inline void reportFatalOnTokenType(const Instruction *I) {
219 if (I->getType()->isTokenTy())
220 report_fatal_error("A token is encountered but SPIR-V without extensions "
221 "does not support token type",
222 false);
223}
224
225void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
226 Value *Arg) {
227 Value *OfType = PoisonValue::get(Ty);
228 CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
229 {Arg->getType()}, OfType, Arg, {}, B);
230 GR->addAssignPtrTypeInstr(Arg, AssignCI);
231}
232
233void SPIRVEmitIntrinsics::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,
234 Value *Arg) {
235 Value *OfType = PoisonValue::get(ElemTy);
236 CallInst *AssignPtrTyCI = GR->findAssignPtrTypeInstr(Arg);
237 if (AssignPtrTyCI == nullptr ||
238 AssignPtrTyCI->getParent()->getParent() != F) {
239 AssignPtrTyCI = buildIntrWithMD(
240 Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
241 {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
242 GR->addDeducedElementType(AssignPtrTyCI, ElemTy);
243 GR->addDeducedElementType(Arg, ElemTy);
244 GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
245 } else {
246 updateAssignType(AssignPtrTyCI, Arg, OfType);
247 }
248}
249
250void SPIRVEmitIntrinsics::updateAssignType(CallInst *AssignCI, Value *Arg,
251 Value *OfType) {
252 AssignCI->setArgOperand(1, buildMD(OfType));
253 if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=
254 Intrinsic::spv_assign_ptr_type)
255 return;
256
257 // update association with the pointee type
258 Type *ElemTy = OfType->getType();
259 GR->addDeducedElementType(AssignCI, ElemTy);
260 GR->addDeducedElementType(Arg, ElemTy);
261}
262
263// Set element pointer type to the given value of ValueTy and tries to
264// specify this type further (recursively) by Operand value, if needed.
265Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
266 Type *ValueTy, Value *Operand, std::unordered_set<Value *> &Visited) {
267 Type *Ty = ValueTy;
268 if (Operand) {
269 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
270 if (Type *NestedTy = deduceElementTypeHelper(Operand, Visited))
271 Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
272 } else {
273 Ty = deduceNestedTypeHelper(dyn_cast<User>(Operand), Ty, Visited);
274 }
275 }
276 return Ty;
277}
278
279// Traverse User instructions to deduce an element pointer type of the operand.
280Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
281 Value *Op, std::unordered_set<Value *> &Visited) {
282 if (!Op || !isPointerTy(Op->getType()))
283 return nullptr;
284
285 if (auto PType = dyn_cast<TypedPointerType>(Op->getType()))
286 return PType->getElementType();
287
288 // maybe we already know operand's element type
289 if (Type *KnownTy = GR->findDeducedElementType(Op))
290 return KnownTy;
291
292 for (User *OpU : Op->users()) {
293 if (Instruction *Inst = dyn_cast<Instruction>(OpU)) {
294 if (Type *Ty = deduceElementTypeHelper(Inst, Visited))
295 return Ty;
296 }
297 }
298 return nullptr;
299}
300
301// Implements what we know in advance about intrinsics and builtin calls
302// TODO: consider feasibility of this particular case to be generalized by
303// encoding knowledge about intrinsics and builtin calls by corresponding
304// specification rules
306 Function *CalledF, unsigned OpIdx) {
307 if ((DemangledName.starts_with("__spirv_ocl_printf(") ||
308 DemangledName.starts_with("printf(")) &&
309 OpIdx == 0)
310 return IntegerType::getInt8Ty(CalledF->getContext());
311 return nullptr;
312}
313
314// Deduce and return a successfully deduced Type of the Instruction,
315// or nullptr otherwise.
316Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I) {
317 std::unordered_set<Value *> Visited;
318 return deduceElementTypeHelper(I, Visited);
319}
320
321Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
322 Value *I, std::unordered_set<Value *> &Visited) {
323 // allow to pass nullptr as an argument
324 if (!I)
325 return nullptr;
326
327 // maybe already known
328 if (Type *KnownTy = GR->findDeducedElementType(I))
329 return KnownTy;
330
331 // maybe a cycle
332 if (Visited.find(I) != Visited.end())
333 return nullptr;
334 Visited.insert(I);
335
336 // fallback value in case when we fail to deduce a type
337 Type *Ty = nullptr;
338 // look for known basic patterns of type inference
339 if (auto *Ref = dyn_cast<AllocaInst>(I)) {
340 Ty = Ref->getAllocatedType();
341 } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
342 Ty = Ref->getResultElementType();
343 } else if (auto *Ref = dyn_cast<GlobalValue>(I)) {
344 Ty = deduceElementTypeByValueDeep(
345 Ref->getValueType(),
346 Ref->getNumOperands() > 0 ? Ref->getOperand(0) : nullptr, Visited);
347 } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
348 Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited);
349 } else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
350 if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy();
351 isPointerTy(Src) && isPointerTy(Dest))
352 Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited);
353 } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
354 Value *Op = Ref->getNewValOperand();
355 Ty = deduceElementTypeByValueDeep(Op->getType(), Op, Visited);
356 } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
357 Value *Op = Ref->getValOperand();
358 Ty = deduceElementTypeByValueDeep(Op->getType(), Op, Visited);
359 } else if (auto *Ref = dyn_cast<PHINode>(I)) {
360 for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) {
361 Ty = deduceElementTypeByUsersDeep(Ref->getIncomingValue(i), Visited);
362 if (Ty)
363 break;
364 }
365 } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
366 for (Value *Op : {Ref->getTrueValue(), Ref->getFalseValue()}) {
367 Ty = deduceElementTypeByUsersDeep(Op, Visited);
368 if (Ty)
369 break;
370 }
371 } else if (auto *CI = dyn_cast<CallInst>(I)) {
372 static StringMap<unsigned> ResTypeByArg = {
373 {"to_global", 0},
374 {"to_local", 0},
375 {"to_private", 0},
376 {"__spirv_GenericCastToPtr_ToGlobal", 0},
377 {"__spirv_GenericCastToPtr_ToLocal", 0},
378 {"__spirv_GenericCastToPtr_ToPrivate", 0},
379 {"__spirv_GenericCastToPtrExplicit_ToGlobal", 0},
380 {"__spirv_GenericCastToPtrExplicit_ToLocal", 0},
381 {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}};
382 // TODO: maybe improve performance by caching demangled names
383 if (Function *CalledF = CI->getCalledFunction()) {
384 std::string DemangledName =
385 getOclOrSpirvBuiltinDemangledName(CalledF->getName());
386 auto AsArgIt = ResTypeByArg.find(DemangledName);
387 if (AsArgIt != ResTypeByArg.end())
388 Ty = deduceElementTypeHelper(CI->getArgOperand(AsArgIt->second),
389 Visited);
390 }
391 }
392
393 // remember the found relationship
394 if (Ty) {
395 // specify nested types if needed, otherwise return unchanged
396 GR->addDeducedElementType(I, Ty);
397 }
398
399 return Ty;
400}
401
402// Re-create a type of the value if it has untyped pointer fields, also nested.
403// Return the original value type if no corrections of untyped pointer
404// information is found or needed.
405Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U) {
406 std::unordered_set<Value *> Visited;
407 return deduceNestedTypeHelper(U, U->getType(), Visited);
408}
409
410Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(
411 User *U, Type *OrigTy, std::unordered_set<Value *> &Visited) {
412 if (!U)
413 return OrigTy;
414
415 // maybe already known
416 if (Type *KnownTy = GR->findDeducedCompositeType(U))
417 return KnownTy;
418
419 // maybe a cycle
420 if (Visited.find(U) != Visited.end())
421 return OrigTy;
422 Visited.insert(U);
423
424 if (dyn_cast<StructType>(OrigTy)) {
426 bool Change = false;
427 for (unsigned i = 0; i < U->getNumOperands(); ++i) {
428 Value *Op = U->getOperand(i);
429 Type *OpTy = Op->getType();
430 Type *Ty = OpTy;
431 if (Op) {
432 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
433 if (Type *NestedTy = deduceElementTypeHelper(Op, Visited))
434 Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
435 } else {
436 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited);
437 }
438 }
439 Tys.push_back(Ty);
440 Change |= Ty != OpTy;
441 }
442 if (Change) {
443 Type *NewTy = StructType::create(Tys);
444 GR->addDeducedCompositeType(U, NewTy);
445 return NewTy;
446 }
447 } else if (auto *ArrTy = dyn_cast<ArrayType>(OrigTy)) {
448 if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
449 Type *OpTy = ArrTy->getElementType();
450 Type *Ty = OpTy;
451 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
452 if (Type *NestedTy = deduceElementTypeHelper(Op, Visited))
453 Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
454 } else {
455 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited);
456 }
457 if (Ty != OpTy) {
458 Type *NewTy = ArrayType::get(Ty, ArrTy->getNumElements());
459 GR->addDeducedCompositeType(U, NewTy);
460 return NewTy;
461 }
462 }
463 } else if (auto *VecTy = dyn_cast<VectorType>(OrigTy)) {
464 if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
465 Type *OpTy = VecTy->getElementType();
466 Type *Ty = OpTy;
467 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
468 if (Type *NestedTy = deduceElementTypeHelper(Op, Visited))
469 Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
470 } else {
471 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited);
472 }
473 if (Ty != OpTy) {
474 Type *NewTy = VectorType::get(Ty, VecTy->getElementCount());
475 GR->addDeducedCompositeType(U, NewTy);
476 return NewTy;
477 }
478 }
479 }
480
481 return OrigTy;
482}
483
484Type *SPIRVEmitIntrinsics::deduceElementType(Value *I, bool UnknownElemTypeI8) {
485 if (Type *Ty = deduceElementTypeHelper(I))
486 return Ty;
487 return UnknownElemTypeI8 ? IntegerType::getInt8Ty(I->getContext()) : nullptr;
488}
489
490// If the Instruction has Pointer operands with unresolved types, this function
491// tries to deduce them. If the Instruction has Pointer operands with known
492// types which differ from expected, this function tries to insert a bitcast to
493// resolve the issue.
494void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) {
496 Type *KnownElemTy = nullptr;
497 // look for known basic patterns of type inference
498 if (auto *Ref = dyn_cast<PHINode>(I)) {
499 if (!isPointerTy(I->getType()) ||
500 !(KnownElemTy = GR->findDeducedElementType(I)))
501 return;
502 for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) {
503 Value *Op = Ref->getIncomingValue(i);
504 if (isPointerTy(Op->getType()))
505 Ops.push_back(std::make_pair(Op, i));
506 }
507 } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
508 if (!isPointerTy(I->getType()) ||
509 !(KnownElemTy = GR->findDeducedElementType(I)))
510 return;
511 for (unsigned i = 0; i < Ref->getNumOperands(); i++) {
512 Value *Op = Ref->getOperand(i);
513 if (isPointerTy(Op->getType()))
514 Ops.push_back(std::make_pair(Op, i));
515 }
516 } else if (auto *Ref = dyn_cast<ReturnInst>(I)) {
517 Type *RetTy = F->getReturnType();
518 if (!isPointerTy(RetTy))
519 return;
520 Value *Op = Ref->getReturnValue();
521 if (!Op)
522 return;
523 if (!(KnownElemTy = GR->findDeducedElementType(F))) {
524 if (Type *OpElemTy = GR->findDeducedElementType(Op)) {
525 GR->addDeducedElementType(F, OpElemTy);
526 TypedPointerType *DerivedTy =
528 GR->addReturnType(F, DerivedTy);
529 }
530 return;
531 }
532 Ops.push_back(std::make_pair(Op, 0));
533 } else if (auto *Ref = dyn_cast<ICmpInst>(I)) {
534 if (!isPointerTy(Ref->getOperand(0)->getType()))
535 return;
536 Value *Op0 = Ref->getOperand(0);
537 Value *Op1 = Ref->getOperand(1);
538 Type *ElemTy0 = GR->findDeducedElementType(Op0);
539 Type *ElemTy1 = GR->findDeducedElementType(Op1);
540 if (ElemTy0) {
541 KnownElemTy = ElemTy0;
542 Ops.push_back(std::make_pair(Op1, 1));
543 } else if (ElemTy1) {
544 KnownElemTy = ElemTy1;
545 Ops.push_back(std::make_pair(Op0, 0));
546 }
547 }
548
549 // There is no enough info to deduce types or all is valid.
550 if (!KnownElemTy || Ops.size() == 0)
551 return;
552
553 LLVMContext &Ctx = F->getContext();
554 IRBuilder<> B(Ctx);
555 for (auto &OpIt : Ops) {
556 Value *Op = OpIt.first;
557 if (Op->use_empty())
558 continue;
559 Type *Ty = GR->findDeducedElementType(Op);
560 if (Ty == KnownElemTy)
561 continue;
562 Value *OpTyVal = Constant::getNullValue(KnownElemTy);
563 Type *OpTy = Op->getType();
564 if (!Ty) {
565 GR->addDeducedElementType(Op, KnownElemTy);
566 // check if there is existing Intrinsic::spv_assign_ptr_type instruction
567 CallInst *AssignCI = GR->findAssignPtrTypeInstr(Op);
568 if (AssignCI == nullptr) {
569 Instruction *User = dyn_cast<Instruction>(Op->use_begin()->get());
570 setInsertPointSkippingPhis(B, User ? User->getNextNode() : I);
571 CallInst *CI =
572 buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op,
573 {B.getInt32(getPointerAddressSpace(OpTy))}, B);
574 GR->addAssignPtrTypeInstr(Op, CI);
575 } else {
576 updateAssignType(AssignCI, Op, OpTyVal);
577 }
578 } else {
579 if (auto *OpI = dyn_cast<Instruction>(Op)) {
580 // spv_ptrcast's argument Op denotes an instruction that generates
581 // a value, and we may use getInsertionPointAfterDef()
582 B.SetInsertPoint(*OpI->getInsertionPointAfterDef());
583 B.SetCurrentDebugLocation(OpI->getDebugLoc());
584 } else if (auto *OpA = dyn_cast<Argument>(Op)) {
585 B.SetInsertPointPastAllocas(OpA->getParent());
586 B.SetCurrentDebugLocation(DebugLoc());
587 } else {
588 B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
589 }
590 SmallVector<Type *, 2> Types = {OpTy, OpTy};
591 SmallVector<Value *, 2> Args = {Op, buildMD(OpTyVal),
592 B.getInt32(getPointerAddressSpace(OpTy))};
593 CallInst *PtrCastI =
594 B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
595 I->setOperand(OpIt.second, PtrCastI);
596 }
597 }
598}
599
600void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
601 Instruction *New,
602 IRBuilder<> &B) {
603 while (!Old->user_empty()) {
604 auto *U = Old->user_back();
605 if (isAssignTypeInstr(U)) {
606 B.SetInsertPoint(U);
607 SmallVector<Value *, 2> Args = {New, U->getOperand(1)};
608 CallInst *AssignCI =
609 B.CreateIntrinsic(Intrinsic::spv_assign_type, {New->getType()}, Args);
610 GR->addAssignPtrTypeInstr(New, AssignCI);
611 U->eraseFromParent();
612 } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) ||
613 isa<CallInst>(U)) {
614 U->replaceUsesOfWith(Old, New);
615 } else {
616 llvm_unreachable("illegal aggregate intrinsic user");
617 }
618 }
619 Old->eraseFromParent();
620}
621
622void SPIRVEmitIntrinsics::preprocessUndefs(IRBuilder<> &B) {
623 std::queue<Instruction *> Worklist;
624 for (auto &I : instructions(F))
625 Worklist.push(&I);
626
627 while (!Worklist.empty()) {
628 Instruction *I = Worklist.front();
629 bool BPrepared = false;
630 Worklist.pop();
631
632 for (auto &Op : I->operands()) {
633 auto *AggrUndef = dyn_cast<UndefValue>(Op);
634 if (!AggrUndef || !Op->getType()->isAggregateType())
635 continue;
636
637 if (!BPrepared) {
639 BPrepared = true;
640 }
641 auto *IntrUndef = B.CreateIntrinsic(Intrinsic::spv_undef, {}, {});
642 Worklist.push(IntrUndef);
643 I->replaceUsesOfWith(Op, IntrUndef);
644 AggrConsts[IntrUndef] = AggrUndef;
645 AggrConstTypes[IntrUndef] = AggrUndef->getType();
646 }
647 }
648}
649
650void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
651 std::queue<Instruction *> Worklist;
652 for (auto &I : instructions(F))
653 Worklist.push(&I);
654
655 while (!Worklist.empty()) {
656 auto *I = Worklist.front();
657 bool IsPhi = isa<PHINode>(I), BPrepared = false;
658 assert(I);
659 bool KeepInst = false;
660 for (const auto &Op : I->operands()) {
661 Constant *AggrConst = nullptr;
662 Type *ResTy = nullptr;
663 if (auto *COp = dyn_cast<ConstantVector>(Op)) {
664 AggrConst = cast<Constant>(COp);
665 ResTy = COp->getType();
666 } else if (auto *COp = dyn_cast<ConstantArray>(Op)) {
667 AggrConst = cast<Constant>(COp);
668 ResTy = B.getInt32Ty();
669 } else if (auto *COp = dyn_cast<ConstantStruct>(Op)) {
670 AggrConst = cast<Constant>(COp);
671 ResTy = B.getInt32Ty();
672 } else if (auto *COp = dyn_cast<ConstantDataArray>(Op)) {
673 AggrConst = cast<Constant>(COp);
674 ResTy = B.getInt32Ty();
675 } else if (auto *COp = dyn_cast<ConstantAggregateZero>(Op)) {
676 AggrConst = cast<Constant>(COp);
677 ResTy = Op->getType()->isVectorTy() ? COp->getType() : B.getInt32Ty();
678 }
679 if (AggrConst) {
681 if (auto *COp = dyn_cast<ConstantDataSequential>(Op))
682 for (unsigned i = 0; i < COp->getNumElements(); ++i)
683 Args.push_back(COp->getElementAsConstant(i));
684 else
685 for (auto &COp : AggrConst->operands())
686 Args.push_back(COp);
687 if (!BPrepared) {
688 IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
689 : B.SetInsertPoint(I);
690 BPrepared = true;
691 }
692 auto *CI =
693 B.CreateIntrinsic(Intrinsic::spv_const_composite, {ResTy}, {Args});
694 Worklist.push(CI);
695 I->replaceUsesOfWith(Op, CI);
696 KeepInst = true;
697 AggrConsts[CI] = AggrConst;
698 AggrConstTypes[CI] = deduceNestedTypeHelper(AggrConst);
699 }
700 }
701 if (!KeepInst)
702 Worklist.pop();
703 }
704}
705
706Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
707 if (!Call.isInlineAsm())
708 return &Call;
709
710 const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
711 LLVMContext &Ctx = F->getContext();
712
713 Constant *TyC = UndefValue::get(IA->getFunctionType());
714 MDString *ConstraintString = MDString::get(Ctx, IA->getConstraintString());
716 buildMD(TyC),
717 MetadataAsValue::get(Ctx, MDNode::get(Ctx, ConstraintString))};
718 for (unsigned OpIdx = 0; OpIdx < Call.arg_size(); OpIdx++)
719 Args.push_back(Call.getArgOperand(OpIdx));
720
721 IRBuilder<> B(Call.getParent());
722 B.SetInsertPoint(&Call);
723 B.CreateIntrinsic(Intrinsic::spv_inline_asm, {}, {Args});
724 return &Call;
725}
726
727Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
728 BasicBlock *ParentBB = I.getParent();
729 IRBuilder<> B(ParentBB);
730 B.SetInsertPoint(&I);
733 for (auto &Op : I.operands()) {
734 if (Op.get()->getType()->isSized()) {
735 Args.push_back(Op);
736 } else if (BasicBlock *BB = dyn_cast<BasicBlock>(Op.get())) {
737 BBCases.push_back(BB);
738 Args.push_back(BlockAddress::get(BB->getParent(), BB));
739 } else {
740 report_fatal_error("Unexpected switch operand");
741 }
742 }
743 CallInst *NewI = B.CreateIntrinsic(Intrinsic::spv_switch,
744 {I.getOperand(0)->getType()}, {Args});
745 // remove switch to avoid its unneeded and undesirable unwrap into branches
746 // and conditions
747 I.replaceAllUsesWith(NewI);
748 I.eraseFromParent();
749 // insert artificial and temporary instruction to preserve valid CFG,
750 // it will be removed after IR translation pass
751 B.SetInsertPoint(ParentBB);
752 IndirectBrInst *BrI = B.CreateIndirectBr(
753 Constant::getNullValue(PointerType::getUnqual(ParentBB->getContext())),
754 BBCases.size());
755 for (BasicBlock *BBCase : BBCases)
756 BrI->addDestination(BBCase);
757 return BrI;
758}
759
760Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
761 IRBuilder<> B(I.getParent());
762 B.SetInsertPoint(&I);
763 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
765 Args.push_back(B.getInt1(I.isInBounds()));
766 for (auto &Op : I.operands())
767 Args.push_back(Op);
768 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
769 I.replaceAllUsesWith(NewI);
770 I.eraseFromParent();
771 return NewI;
772}
773
774Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
775 IRBuilder<> B(I.getParent());
776 B.SetInsertPoint(&I);
777 Value *Source = I.getOperand(0);
778
779 // SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of
780 // varying element types. In case of IR coming from older versions of LLVM
781 // such bitcasts do not provide sufficient information, should be just skipped
782 // here, and handled in insertPtrCastOrAssignTypeInstr.
783 if (isPointerTy(I.getType())) {
784 I.replaceAllUsesWith(Source);
785 I.eraseFromParent();
786 return nullptr;
787 }
788
789 SmallVector<Type *, 2> Types = {I.getType(), Source->getType()};
790 SmallVector<Value *> Args(I.op_begin(), I.op_end());
791 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args});
792 std::string InstName = I.hasName() ? I.getName().str() : "";
793 I.replaceAllUsesWith(NewI);
794 I.eraseFromParent();
795 NewI->setName(InstName);
796 return NewI;
797}
798
799void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
800 TargetExtType *AssignedType, Value *V, IRBuilder<> &B) {
801 Type *VTy = V->getType();
802
803 // A couple of sanity checks.
804 assert(isPointerTy(VTy) && "Expect a pointer type!");
805 if (auto PType = dyn_cast<TypedPointerType>(VTy))
806 if (PType->getElementType() != AssignedType)
807 report_fatal_error("Unexpected pointer element type!");
808
809 CallInst *AssignCI = GR->findAssignPtrTypeInstr(V);
810 if (!AssignCI) {
811 buildAssignType(B, AssignedType, V);
812 return;
813 }
814
815 Type *CurrentType =
816 dyn_cast<ConstantAsMetadata>(
817 cast<MetadataAsValue>(AssignCI->getOperand(1))->getMetadata())
818 ->getType();
819 if (CurrentType == AssignedType)
820 return;
821
822 // Builtin types cannot be redeclared or casted.
823 if (CurrentType->isTargetExtTy())
824 report_fatal_error("Type mismatch " + CurrentType->getTargetExtName() +
825 "/" + AssignedType->getTargetExtName() +
826 " for value " + V->getName(),
827 false);
828
829 // Our previous guess about the type seems to be wrong, let's update
830 // inferred type according to a new, more precise type information.
831 updateAssignType(AssignCI, V, PoisonValue::get(AssignedType));
832}
833
834void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
835 Instruction *I, Value *Pointer, Type *ExpectedElementType,
836 unsigned OperandToReplace, IRBuilder<> &B) {
837 // If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source
838 // pointer instead. The BitCastInst should be later removed when visited.
839 while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer))
840 Pointer = BC->getOperand(0);
841
842 // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType
843 Type *PointerElemTy = deduceElementTypeHelper(Pointer);
844 if (PointerElemTy == ExpectedElementType)
845 return;
846
848 MetadataAsValue *VMD = buildMD(PoisonValue::get(ExpectedElementType));
849 unsigned AddressSpace = getPointerAddressSpace(Pointer->getType());
850 bool FirstPtrCastOrAssignPtrType = true;
851
852 // Do not emit new spv_ptrcast if equivalent one already exists or when
853 // spv_assign_ptr_type already targets this pointer with the same element
854 // type.
855 for (auto User : Pointer->users()) {
856 auto *II = dyn_cast<IntrinsicInst>(User);
857 if (!II ||
858 (II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type &&
859 II->getIntrinsicID() != Intrinsic::spv_ptrcast) ||
860 II->getOperand(0) != Pointer)
861 continue;
862
863 // There is some spv_ptrcast/spv_assign_ptr_type already targeting this
864 // pointer.
865 FirstPtrCastOrAssignPtrType = false;
866 if (II->getOperand(1) != VMD ||
867 dyn_cast<ConstantInt>(II->getOperand(2))->getSExtValue() !=
869 continue;
870
871 // The spv_ptrcast/spv_assign_ptr_type targeting this pointer is of the same
872 // element type and address space.
873 if (II->getIntrinsicID() != Intrinsic::spv_ptrcast)
874 return;
875
876 // This must be a spv_ptrcast, do not emit new if this one has the same BB
877 // as I. Otherwise, search for other spv_ptrcast/spv_assign_ptr_type.
878 if (II->getParent() != I->getParent())
879 continue;
880
881 I->setOperand(OperandToReplace, II);
882 return;
883 }
884
885 // // Do not emit spv_ptrcast if it would cast to the default pointer element
886 // // type (i8) of the same address space.
887 // if (ExpectedElementType->isIntegerTy(8))
888 // return;
889
890 // If this would be the first spv_ptrcast, do not emit spv_ptrcast and emit
891 // spv_assign_ptr_type instead.
892 if (FirstPtrCastOrAssignPtrType &&
893 (isa<Instruction>(Pointer) || isa<Argument>(Pointer))) {
894 buildAssignPtr(B, ExpectedElementType, Pointer);
895 return;
896 }
897
898 // Emit spv_ptrcast
899 SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
901 auto *PtrCastI = B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
902 I->setOperand(OperandToReplace, PtrCastI);
903}
904
905void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
906 IRBuilder<> &B) {
907 // Handle basic instructions:
908 StoreInst *SI = dyn_cast<StoreInst>(I);
909 if (SI && F->getCallingConv() == CallingConv::SPIR_KERNEL &&
910 isPointerTy(SI->getValueOperand()->getType()) &&
911 isa<Argument>(SI->getValueOperand())) {
912 return replacePointerOperandWithPtrCast(
913 I, SI->getValueOperand(), IntegerType::getInt8Ty(F->getContext()), 0,
914 B);
915 } else if (SI) {
916 return replacePointerOperandWithPtrCast(
917 I, SI->getPointerOperand(), SI->getValueOperand()->getType(), 1, B);
918 } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
919 return replacePointerOperandWithPtrCast(I, LI->getPointerOperand(),
920 LI->getType(), 0, B);
921 } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
922 return replacePointerOperandWithPtrCast(I, GEPI->getPointerOperand(),
923 GEPI->getSourceElementType(), 0, B);
924 }
925
926 // Handle calls to builtins (non-intrinsics):
927 CallInst *CI = dyn_cast<CallInst>(I);
928 if (!CI || CI->isIndirectCall() || CI->isInlineAsm() ||
930 return;
931
932 // collect information about formal parameter types
933 std::string DemangledName =
935 Function *CalledF = CI->getCalledFunction();
936 SmallVector<Type *, 4> CalledArgTys;
937 bool HaveTypes = false;
938 for (unsigned OpIdx = 0; OpIdx < CalledF->arg_size(); ++OpIdx) {
939 Argument *CalledArg = CalledF->getArg(OpIdx);
940 Type *ArgType = CalledArg->getType();
941 if (!isPointerTy(ArgType)) {
942 CalledArgTys.push_back(nullptr);
943 } else if (isTypedPointerTy(ArgType)) {
944 CalledArgTys.push_back(cast<TypedPointerType>(ArgType)->getElementType());
945 HaveTypes = true;
946 } else {
947 Type *ElemTy = GR->findDeducedElementType(CalledArg);
948 if (!ElemTy && hasPointeeTypeAttr(CalledArg))
949 ElemTy = getPointeeTypeByAttr(CalledArg);
950 if (!ElemTy) {
951 ElemTy = getPointeeTypeByCallInst(DemangledName, CalledF, OpIdx);
952 if (ElemTy) {
953 GR->addDeducedElementType(CalledArg, ElemTy);
954 } else {
955 for (User *U : CalledArg->users()) {
956 if (Instruction *Inst = dyn_cast<Instruction>(U)) {
957 if ((ElemTy = deduceElementTypeHelper(Inst)) != nullptr)
958 break;
959 }
960 }
961 }
962 }
963 HaveTypes |= ElemTy != nullptr;
964 CalledArgTys.push_back(ElemTy);
965 }
966 }
967
968 if (DemangledName.empty() && !HaveTypes)
969 return;
970
971 for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) {
972 Value *ArgOperand = CI->getArgOperand(OpIdx);
973 if (!isPointerTy(ArgOperand->getType()))
974 continue;
975
976 // Constants (nulls/undefs) are handled in insertAssignPtrTypeIntrs()
977 if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand)) {
978 // However, we may have assumptions about the formal argument's type and
979 // may have a need to insert a ptr cast for the actual parameter of this
980 // call.
981 Argument *CalledArg = CalledF->getArg(OpIdx);
982 if (!GR->findDeducedElementType(CalledArg))
983 continue;
984 }
985
986 Type *ExpectedType =
987 OpIdx < CalledArgTys.size() ? CalledArgTys[OpIdx] : nullptr;
988 if (!ExpectedType && !DemangledName.empty())
990 DemangledName, OpIdx, I->getContext());
991 if (!ExpectedType)
992 continue;
993
994 if (ExpectedType->isTargetExtTy())
995 insertAssignPtrTypeTargetExt(cast<TargetExtType>(ExpectedType),
996 ArgOperand, B);
997 else
998 replacePointerOperandWithPtrCast(CI, ArgOperand, ExpectedType, OpIdx, B);
999 }
1000}
1001
1002Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
1003 SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
1004 I.getOperand(1)->getType(),
1005 I.getOperand(2)->getType()};
1006 IRBuilder<> B(I.getParent());
1007 B.SetInsertPoint(&I);
1008 SmallVector<Value *> Args(I.op_begin(), I.op_end());
1009 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
1010 std::string InstName = I.hasName() ? I.getName().str() : "";
1011 I.replaceAllUsesWith(NewI);
1012 I.eraseFromParent();
1013 NewI->setName(InstName);
1014 return NewI;
1015}
1016
1018SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
1019 IRBuilder<> B(I.getParent());
1020 B.SetInsertPoint(&I);
1021 SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
1022 I.getIndexOperand()->getType()};
1023 SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()};
1024 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
1025 std::string InstName = I.hasName() ? I.getName().str() : "";
1026 I.replaceAllUsesWith(NewI);
1027 I.eraseFromParent();
1028 NewI->setName(InstName);
1029 return NewI;
1030}
1031
1032Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
1033 IRBuilder<> B(I.getParent());
1034 B.SetInsertPoint(&I);
1035 SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()};
1037 for (auto &Op : I.operands())
1038 if (isa<UndefValue>(Op))
1039 Args.push_back(UndefValue::get(B.getInt32Ty()));
1040 else
1041 Args.push_back(Op);
1042 for (auto &Op : I.indices())
1043 Args.push_back(B.getInt32(Op));
1044 Instruction *NewI =
1045 B.CreateIntrinsic(Intrinsic::spv_insertv, {Types}, {Args});
1046 replaceMemInstrUses(&I, NewI, B);
1047 return NewI;
1048}
1049
1050Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
1051 IRBuilder<> B(I.getParent());
1052 B.SetInsertPoint(&I);
1054 for (auto &Op : I.operands())
1055 Args.push_back(Op);
1056 for (auto &Op : I.indices())
1057 Args.push_back(B.getInt32(Op));
1058 auto *NewI =
1059 B.CreateIntrinsic(Intrinsic::spv_extractv, {I.getType()}, {Args});
1060 I.replaceAllUsesWith(NewI);
1061 I.eraseFromParent();
1062 return NewI;
1063}
1064
1065Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) {
1066 if (!I.getType()->isAggregateType())
1067 return &I;
1068 IRBuilder<> B(I.getParent());
1069 B.SetInsertPoint(&I);
1070 TrackConstants = false;
1071 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
1073 TLI->getLoadMemOperandFlags(I, F->getDataLayout());
1074 auto *NewI =
1075 B.CreateIntrinsic(Intrinsic::spv_load, {I.getOperand(0)->getType()},
1076 {I.getPointerOperand(), B.getInt16(Flags),
1077 B.getInt8(I.getAlign().value())});
1078 replaceMemInstrUses(&I, NewI, B);
1079 return NewI;
1080}
1081
1082Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
1083 if (!AggrStores.contains(&I))
1084 return &I;
1085 IRBuilder<> B(I.getParent());
1086 B.SetInsertPoint(&I);
1087 TrackConstants = false;
1088 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
1090 TLI->getStoreMemOperandFlags(I, F->getDataLayout());
1091 auto *PtrOp = I.getPointerOperand();
1092 auto *NewI = B.CreateIntrinsic(
1093 Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
1094 {I.getValueOperand(), PtrOp, B.getInt16(Flags),
1095 B.getInt8(I.getAlign().value())});
1096 I.eraseFromParent();
1097 return NewI;
1098}
1099
1100Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) {
1101 Value *ArraySize = nullptr;
1102 if (I.isArrayAllocation()) {
1103 const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I.getFunction());
1104 if (!STI->canUseExtension(
1105 SPIRV::Extension::SPV_INTEL_variable_length_array))
1107 "array allocation: this instruction requires the following "
1108 "SPIR-V extension: SPV_INTEL_variable_length_array",
1109 false);
1110 ArraySize = I.getArraySize();
1111 }
1112 IRBuilder<> B(I.getParent());
1113 B.SetInsertPoint(&I);
1114 TrackConstants = false;
1115 Type *PtrTy = I.getType();
1116 auto *NewI =
1117 ArraySize ? B.CreateIntrinsic(Intrinsic::spv_alloca_array,
1118 {PtrTy, ArraySize->getType()}, {ArraySize})
1119 : B.CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {});
1120 std::string InstName = I.hasName() ? I.getName().str() : "";
1121 I.replaceAllUsesWith(NewI);
1122 I.eraseFromParent();
1123 NewI->setName(InstName);
1124 return NewI;
1125}
1126
1127Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
1128 assert(I.getType()->isAggregateType() && "Aggregate result is expected");
1129 IRBuilder<> B(I.getParent());
1130 B.SetInsertPoint(&I);
1132 for (auto &Op : I.operands())
1133 Args.push_back(Op);
1134 Args.push_back(B.getInt32(I.getSyncScopeID()));
1135 Args.push_back(B.getInt32(
1136 static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering()))));
1137 Args.push_back(B.getInt32(
1138 static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering()))));
1139 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_cmpxchg,
1140 {I.getPointerOperand()->getType()}, {Args});
1141 replaceMemInstrUses(&I, NewI, B);
1142 return NewI;
1143}
1144
1145Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
1146 IRBuilder<> B(I.getParent());
1147 B.SetInsertPoint(&I);
1148 B.CreateIntrinsic(Intrinsic::spv_unreachable, {}, {});
1149 return &I;
1150}
1151
1152void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
1153 IRBuilder<> &B) {
1154 // Skip special artifical variable llvm.global.annotations.
1155 if (GV.getName() == "llvm.global.annotations")
1156 return;
1157 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1158 // Deduce element type and store results in Global Registry.
1159 // Result is ignored, because TypedPointerType is not supported
1160 // by llvm IR general logic.
1161 deduceElementTypeHelper(&GV);
1163 Type *Ty = isAggrConstForceInt32(Init) ? B.getInt32Ty() : Init->getType();
1164 Constant *Const = isAggrConstForceInt32(Init) ? B.getInt32(1) : Init;
1165 auto *InitInst = B.CreateIntrinsic(Intrinsic::spv_init_global,
1166 {GV.getType(), Ty}, {&GV, Const});
1167 InitInst->setArgOperand(1, Init);
1168 }
1169 if ((!GV.hasInitializer() || isa<UndefValue>(GV.getInitializer())) &&
1170 GV.getNumUses() == 0)
1171 B.CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV);
1172}
1173
1174// Return true, if we can't decide what is the pointee type now and will get
1175// back to the question later. Return false is spv_assign_ptr_type is not needed
1176// or can be inserted immediately.
1177bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
1178 IRBuilder<> &B,
1179 bool UnknownElemTypeI8) {
1181 if (!isPointerTy(I->getType()) || !requireAssignType(I) ||
1182 isa<BitCastInst>(I))
1183 return false;
1184
1186 if (Type *ElemTy = deduceElementType(I, UnknownElemTypeI8)) {
1187 buildAssignPtr(B, ElemTy, I);
1188 return false;
1189 }
1190 return true;
1191}
1192
1193void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
1194 IRBuilder<> &B) {
1196 Type *Ty = I->getType();
1197 if (!Ty->isVoidTy() && !isPointerTy(Ty) && requireAssignType(I)) {
1199 Type *TypeToAssign = Ty;
1200 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1201 if (II->getIntrinsicID() == Intrinsic::spv_const_composite ||
1202 II->getIntrinsicID() == Intrinsic::spv_undef) {
1203 auto It = AggrConstTypes.find(II);
1204 if (It == AggrConstTypes.end())
1205 report_fatal_error("Unknown composite intrinsic type");
1206 TypeToAssign = It->second;
1207 }
1208 }
1209 buildAssignType(B, TypeToAssign, I);
1210 }
1211 for (const auto &Op : I->operands()) {
1212 if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
1213 // Check GetElementPtrConstantExpr case.
1214 (isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
1216 Type *OpTy = Op->getType();
1217 if (isa<UndefValue>(Op) && OpTy->isAggregateType()) {
1218 CallInst *AssignCI =
1219 buildIntrWithMD(Intrinsic::spv_assign_type, {B.getInt32Ty()}, Op,
1220 UndefValue::get(B.getInt32Ty()), {}, B);
1221 GR->addAssignPtrTypeInstr(Op, AssignCI);
1222 } else if (!isa<Instruction>(Op)) {
1223 Type *OpTy = Op->getType();
1224 if (auto PType = dyn_cast<TypedPointerType>(OpTy)) {
1225 buildAssignPtr(B, PType->getElementType(), Op);
1226 } else if (isPointerTy(OpTy)) {
1227 Type *ElemTy = GR->findDeducedElementType(Op);
1228 buildAssignPtr(B, ElemTy ? ElemTy : deduceElementType(Op, true), Op);
1229 } else {
1230 CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
1231 {OpTy}, Op, Op, {}, B);
1232 GR->addAssignPtrTypeInstr(Op, AssignCI);
1233 }
1234 }
1235 }
1236 }
1237}
1238
1239void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
1240 IRBuilder<> &B) {
1241 if (MDNode *MD = I->getMetadata("spirv.Decorations")) {
1243 B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
1244 {I, MetadataAsValue::get(I->getContext(), MD)});
1245 }
1246}
1247
1248void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
1249 IRBuilder<> &B) {
1250 auto *II = dyn_cast<IntrinsicInst>(I);
1251 if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite &&
1252 TrackConstants) {
1254 auto t = AggrConsts.find(I);
1255 assert(t != AggrConsts.end());
1256 auto *NewOp =
1257 buildIntrWithMD(Intrinsic::spv_track_constant,
1258 {II->getType(), II->getType()}, t->second, I, {}, B);
1259 I->replaceAllUsesWith(NewOp);
1260 NewOp->setArgOperand(0, I);
1261 }
1262 bool IsPhi = isa<PHINode>(I), BPrepared = false;
1263 for (const auto &Op : I->operands()) {
1264 if (isa<PHINode>(I) || isa<SwitchInst>(I))
1265 TrackConstants = false;
1266 if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
1267 unsigned OpNo = Op.getOperandNo();
1268 if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
1269 (II->paramHasAttr(OpNo, Attribute::ImmArg))))
1270 continue;
1271 if (!BPrepared) {
1272 IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
1273 : B.SetInsertPoint(I);
1274 BPrepared = true;
1275 }
1276 Value *OpTyVal = Op;
1277 if (Op->getType()->isTargetExtTy())
1278 OpTyVal = PoisonValue::get(Op->getType());
1279 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
1280 {Op->getType(), OpTyVal->getType()}, Op,
1281 OpTyVal, {}, B);
1282 I->setOperand(OpNo, NewOp);
1283 }
1284 }
1285 if (I->hasName()) {
1288 std::vector<Value *> Args = {I};
1289 addStringImm(I->getName(), B, Args);
1290 B.CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
1291 }
1292}
1293
1294Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F,
1295 unsigned OpIdx) {
1296 std::unordered_set<Function *> FVisited;
1297 return deduceFunParamElementType(F, OpIdx, FVisited);
1298}
1299
1300Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
1301 Function *F, unsigned OpIdx, std::unordered_set<Function *> &FVisited) {
1302 // maybe a cycle
1303 if (FVisited.find(F) != FVisited.end())
1304 return nullptr;
1305 FVisited.insert(F);
1306
1307 std::unordered_set<Value *> Visited;
1309 // search in function's call sites
1310 for (User *U : F->users()) {
1311 CallInst *CI = dyn_cast<CallInst>(U);
1312 if (!CI || OpIdx >= CI->arg_size())
1313 continue;
1314 Value *OpArg = CI->getArgOperand(OpIdx);
1315 if (!isPointerTy(OpArg->getType()))
1316 continue;
1317 // maybe we already know operand's element type
1318 if (Type *KnownTy = GR->findDeducedElementType(OpArg))
1319 return KnownTy;
1320 // try to deduce from the operand itself
1321 Visited.clear();
1322 if (Type *Ty = deduceElementTypeHelper(OpArg, Visited))
1323 return Ty;
1324 // search in actual parameter's users
1325 for (User *OpU : OpArg->users()) {
1326 Instruction *Inst = dyn_cast<Instruction>(OpU);
1327 if (!Inst || Inst == CI)
1328 continue;
1329 Visited.clear();
1330 if (Type *Ty = deduceElementTypeHelper(Inst, Visited))
1331 return Ty;
1332 }
1333 // check if it's a formal parameter of the outer function
1334 if (!CI->getParent() || !CI->getParent()->getParent())
1335 continue;
1336 Function *OuterF = CI->getParent()->getParent();
1337 if (FVisited.find(OuterF) != FVisited.end())
1338 continue;
1339 for (unsigned i = 0; i < OuterF->arg_size(); ++i) {
1340 if (OuterF->getArg(i) == OpArg) {
1341 Lookup.push_back(std::make_pair(OuterF, i));
1342 break;
1343 }
1344 }
1345 }
1346
1347 // search in function parameters
1348 for (auto &Pair : Lookup) {
1349 if (Type *Ty = deduceFunParamElementType(Pair.first, Pair.second, FVisited))
1350 return Ty;
1351 }
1352
1353 return nullptr;
1354}
1355
1356void SPIRVEmitIntrinsics::processParamTypesByFunHeader(Function *F,
1357 IRBuilder<> &B) {
1358 B.SetInsertPointPastAllocas(F);
1359 for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
1360 Argument *Arg = F->getArg(OpIdx);
1361 if (!isUntypedPointerTy(Arg->getType()))
1362 continue;
1363 Type *ElemTy = GR->findDeducedElementType(Arg);
1364 if (!ElemTy && hasPointeeTypeAttr(Arg) &&
1365 (ElemTy = getPointeeTypeByAttr(Arg)) != nullptr)
1366 buildAssignPtr(B, ElemTy, Arg);
1367 }
1368}
1369
1370void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
1371 B.SetInsertPointPastAllocas(F);
1372 for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
1373 Argument *Arg = F->getArg(OpIdx);
1374 if (!isUntypedPointerTy(Arg->getType()))
1375 continue;
1376 Type *ElemTy = GR->findDeducedElementType(Arg);
1377 if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr)
1378 buildAssignPtr(B, ElemTy, Arg);
1379 }
1380}
1381
1382bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
1383 if (Func.isDeclaration())
1384 return false;
1385
1386 const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(Func);
1387 GR = ST.getSPIRVGlobalRegistry();
1388
1389 F = &Func;
1390 IRBuilder<> B(Func.getContext());
1391 AggrConsts.clear();
1392 AggrConstTypes.clear();
1393 AggrStores.clear();
1394
1395 processParamTypesByFunHeader(F, B);
1396
1397 // StoreInst's operand type can be changed during the next transformations,
1398 // so we need to store it in the set. Also store already transformed types.
1399 for (auto &I : instructions(Func)) {
1400 StoreInst *SI = dyn_cast<StoreInst>(&I);
1401 if (!SI)
1402 continue;
1403 Type *ElTy = SI->getValueOperand()->getType();
1404 if (ElTy->isAggregateType() || ElTy->isVectorTy())
1405 AggrStores.insert(&I);
1406 }
1407
1408 B.SetInsertPoint(&Func.getEntryBlock(), Func.getEntryBlock().begin());
1409 for (auto &GV : Func.getParent()->globals())
1410 processGlobalValue(GV, B);
1411
1412 preprocessUndefs(B);
1413 preprocessCompositeConstants(B);
1415 for (auto &I : instructions(Func))
1416 Worklist.push_back(&I);
1417
1418 for (auto &I : Worklist) {
1419 // Don't emit intrinsincs for convergence intrinsics.
1420 if (isConvergenceIntrinsic(I))
1421 continue;
1422
1423 bool Postpone = insertAssignPtrTypeIntrs(I, B, false);
1424 // if Postpone is true, we can't decide on pointee type yet
1425 insertAssignTypeIntrs(I, B);
1426 insertPtrCastOrAssignTypeInstr(I, B);
1428 // if instruction requires a pointee type set, let's check if we know it
1429 // already, and force it to be i8 if not
1430 if (Postpone && !GR->findAssignPtrTypeInstr(I))
1431 insertAssignPtrTypeIntrs(I, B, true);
1432 }
1433
1434 for (auto &I : instructions(Func))
1435 deduceOperandElementType(&I);
1436
1437 for (auto *I : Worklist) {
1438 TrackConstants = true;
1439 if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
1441 // Visitors return either the original/newly created instruction for further
1442 // processing, nullptr otherwise.
1443 I = visit(*I);
1444 if (!I)
1445 continue;
1446
1447 // Don't emit intrinsics for convergence operations.
1448 if (isConvergenceIntrinsic(I))
1449 continue;
1450
1451 processInstrAfterVisit(I, B);
1452 }
1453
1454 return true;
1455}
1456
1457bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
1458 bool Changed = false;
1459
1460 for (auto &F : M) {
1461 Changed |= runOnFunction(F);
1462 }
1463
1464 for (auto &F : M) {
1465 // check if function parameter types are set
1466 if (!F.isDeclaration() && !F.isIntrinsic()) {
1467 const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(F);
1468 GR = ST.getSPIRVGlobalRegistry();
1469 IRBuilder<> B(F.getContext());
1470 processParamTypes(&F, B);
1471 }
1472 }
1473
1474 return Changed;
1475}
1476
1478 return new SPIRVEmitIntrinsics(TM);
1479}
static unsigned getIntrinsicID(const SDNode *N)
aarch64 promote const
unsigned Intr
always inline
Expand Atomic instructions
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
return RetTy
static bool runOnFunction(Function &F, bool PostInlining)
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
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 isAggrConstForceInt32(const Value *V)
static void reportFatalOnTokenType(const Instruction *I)
static void setInsertPointAfterDef(IRBuilder<> &B, Instruction *I)
static Type * getPointeeTypeByCallInst(StringRef DemangledName, Function *CalledF, unsigned OpIdx)
static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I)
static bool requireAssignType(Instruction *I)
static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB)
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
an instruction to allocate memory on the stack
Definition: Instructions.h:60
Represent the analysis usage information of a pass.
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
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:494
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:168
This class represents a no-op cast from one type to another.
static BlockAddress * get(Function *F, BasicBlock *BB)
Return a BlockAddress for the specified function and basic block.
Definition: Constants.cpp:1833
bool isInlineAsm() const
Check if this call is an inline asm statement.
Definition: InstrTypes.h:1532
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1465
bool isIndirectCall() const
Return true if the callsite is an indirect call.
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1410
void setArgOperand(unsigned i, Value *v)
Definition: InstrTypes.h:1415
unsigned arg_size() const
Definition: InstrTypes.h:1408
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:370
This class represents an Operation in the Expression.
A debug info location.
Definition: DebugLoc.h:33
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.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition: Function.h:247
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:358
size_t arg_size() const
Definition: Function.h:864
Argument * getArg(unsigned i) const
Definition: Function.h:849
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:914
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:294
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2664
Indirect Branch Instruction.
void addDestination(BasicBlock *Dest)
Add a destination.
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 visitCallInst(CallInst &I)
Definition: InstVisitor.h:220
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
Definition: InstVisitor.h:174
void visitInstruction(Instruction &I)
Definition: InstVisitor.h:280
RetTy visitLoadInst(LoadInst &I)
Definition: InstVisitor.h:169
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:92
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:169
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:48
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
An instruction for reading from memory.
Definition: Instructions.h:173
Metadata node.
Definition: Metadata.h:1067
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1541
A single uniqued string.
Definition: Metadata.h:720
static MDString * get(LLVMContext &Context, StringRef Str)
Definition: Metadata.cpp:600
Flags
Flags values. These may be or'd together.
Metadata wrapper in the Value hierarchy.
Definition: Metadata.h:176
static MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition: Metadata.cpp:103
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
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...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1814
void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI)
Type * findDeducedCompositeType(const Value *Val)
void addDeducedElementType(Value *Val, Type *Ty)
void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy)
void addDeducedCompositeType(Value *Val, Type *Ty)
Type * findDeducedElementType(const Value *Val)
CallInst * findAssignPtrTypeInstr(const Value *Val)
bool canUseExtension(SPIRV::Extension::Extension E) const
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
An instruction for storing to memory.
Definition: Instructions.h:289
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
iterator end()
Definition: StringMap.h:220
iterator find(StringRef Key)
Definition: StringMap.h:233
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:258
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:513
Multiway switch.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:720
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
StringRef getTargetExtName() const
bool isTargetExtTy() const
Return true if this is a target extension type.
Definition: Type.h:207
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
A few GPU targets, such as DXIL and SPIR-V, have typed pointers.
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1795
This function has undefined behavior.
op_range operands()
Definition: User.h:242
Value * getOperand(unsigned i) const
Definition: User.h:169
static ConstantAsMetadata * getConstant(Value *C)
Definition: Metadata.h:472
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:377
iterator_range< user_iterator > users()
Definition: Value.h:421
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1074
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
const ParentTy * getParent() const
Definition: ilist_node.h:32
#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
@ SPIR_KERNEL
Used for SPIR kernel functions.
Definition: CallingConv.h:144
Type * parseBuiltinCallArgumentBaseType(const StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)
Parses the provided ArgIdx argument base type in the DemangledCall skeleton.
NodeAddr< FuncNode * > Func
Definition: RDFGraph.h:393
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeSPIRVEmitIntrinsicsPass(PassRegistry &)
ModulePass * createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM)
unsigned getPointerAddressSpace(const Type *T)
Definition: SPIRVUtils.h:126
AddressSpace
Definition: NVPTXBaseInfo.h:21
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
Definition: SPIRVUtils.cpp:339
bool isTypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:110
bool isPointerTy(const Type *T)
Definition: SPIRVUtils.h:120
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Ref
The access may reference the value stored in memory.
DWARFExpression::Operation Op
Type * getPointeeTypeByAttr(Argument *Arg)
Definition: SPIRVUtils.h:139
bool hasPointeeTypeAttr(Argument *Arg)
Definition: SPIRVUtils.h:134
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:51
bool isUntypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:115
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
Definition: SPIRVUtils.cpp:236