LLVM 22.0.0git
SPIRVGlobalRegistry.cpp
Go to the documentation of this file.
1//===-- SPIRVGlobalRegistry.cpp - SPIR-V Global Registry --------*- 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// This file contains the implementation of the SPIRVGlobalRegistry class,
10// which is used to maintain rich type information required for SPIR-V even
11// after lowering from LLVM IR to GMIR. It can convert an llvm::Type into
12// an OpTypeXXX instruction, and map it to a virtual register. Also it builds
13// and supports consistency of constants and global variables.
14//
15//===----------------------------------------------------------------------===//
16
17#include "SPIRVGlobalRegistry.h"
18#include "SPIRV.h"
19#include "SPIRVBuiltins.h"
20#include "SPIRVSubtarget.h"
21#include "SPIRVUtils.h"
22#include "llvm/ADT/APInt.h"
23#include "llvm/IR/Constants.h"
25#include "llvm/IR/Function.h"
27#include "llvm/IR/Intrinsics.h"
28#include "llvm/IR/IntrinsicsSPIRV.h"
29#include "llvm/IR/Type.h"
32#include <cassert>
33#include <functional>
34
35using namespace llvm;
36
37static bool allowEmitFakeUse(const Value *Arg) {
38 if (isSpvIntrinsic(Arg))
39 return false;
41 return false;
42 if (const auto *LI = dyn_cast<LoadInst>(Arg))
43 if (LI->getType()->isAggregateType())
44 return false;
45 return true;
46}
47
48static unsigned typeToAddressSpace(const Type *Ty) {
49 if (auto PType = dyn_cast<TypedPointerType>(Ty))
50 return PType->getAddressSpace();
51 if (auto PType = dyn_cast<PointerType>(Ty))
52 return PType->getAddressSpace();
53 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
54 ExtTy && isTypedPointerWrapper(ExtTy))
55 return ExtTy->getIntParameter(0);
56 reportFatalInternalError("Unable to convert LLVM type to SPIRVType");
57}
58
59static bool
60storageClassRequiresExplictLayout(SPIRV::StorageClass::StorageClass SC) {
61 switch (SC) {
62 case SPIRV::StorageClass::Uniform:
63 case SPIRV::StorageClass::PushConstant:
64 case SPIRV::StorageClass::StorageBuffer:
65 case SPIRV::StorageClass::PhysicalStorageBufferEXT:
66 return true;
67 case SPIRV::StorageClass::UniformConstant:
68 case SPIRV::StorageClass::Input:
69 case SPIRV::StorageClass::Output:
70 case SPIRV::StorageClass::Workgroup:
71 case SPIRV::StorageClass::CrossWorkgroup:
72 case SPIRV::StorageClass::Private:
73 case SPIRV::StorageClass::Function:
74 case SPIRV::StorageClass::Generic:
75 case SPIRV::StorageClass::AtomicCounter:
76 case SPIRV::StorageClass::Image:
77 case SPIRV::StorageClass::CallableDataNV:
78 case SPIRV::StorageClass::IncomingCallableDataNV:
79 case SPIRV::StorageClass::RayPayloadNV:
80 case SPIRV::StorageClass::HitAttributeNV:
81 case SPIRV::StorageClass::IncomingRayPayloadNV:
82 case SPIRV::StorageClass::ShaderRecordBufferNV:
83 case SPIRV::StorageClass::CodeSectionINTEL:
84 case SPIRV::StorageClass::DeviceOnlyINTEL:
85 case SPIRV::StorageClass::HostOnlyINTEL:
86 return false;
87 }
88 llvm_unreachable("Unknown SPIRV::StorageClass enum");
89}
90
92 : PointerSize(PointerSize), Bound(0), CurMF(nullptr) {}
93
95 Register VReg,
97 const SPIRVInstrInfo &TII) {
99 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
100 return SpirvType;
101}
102
103SPIRVType *
106 const SPIRVInstrInfo &TII) {
108 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
109 return SpirvType;
110}
111
113 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
114 const SPIRVInstrInfo &TII) {
115 SPIRVType *SpirvType =
117 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
118 return SpirvType;
119}
120
122 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
123 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
124 SPIRVType *SpirvType =
125 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
126 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
127 return SpirvType;
128}
129
131 Register VReg,
132 const MachineFunction &MF) {
133 VRegToTypeMap[&MF][VReg] = SpirvType;
134}
135
137 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(64));
138 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
139 return Res;
140}
141
143 return createTypeVReg(MIRBuilder.getMF().getRegInfo());
144}
145
146SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
147 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
148 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
149 .addDef(createTypeVReg(MIRBuilder));
150 });
151}
152
153unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
154 const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
155 if (ST.canUseExtension(
156 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||
157 (Width == 4 && ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)))
158 return Width;
159 if (Width <= 8)
160 return 8;
161 else if (Width <= 16)
162 return 16;
163 else if (Width <= 32)
164 return 32;
165 else if (Width <= 64)
166 return 64;
167 else if (Width <= 128)
168 return 128;
169 reportFatalUsageError("Unsupported Integer width!");
170}
171
172SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
173 MachineIRBuilder &MIRBuilder,
174 bool IsSigned) {
175 Width = adjustOpTypeIntWidth(Width);
176 const SPIRVSubtarget &ST =
178 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
179 if (Width == 4 && ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
180 MIRBuilder.buildInstr(SPIRV::OpExtension)
181 .addImm(SPIRV::Extension::SPV_INTEL_int4);
182 MIRBuilder.buildInstr(SPIRV::OpCapability)
183 .addImm(SPIRV::Capability::Int4TypeINTEL);
184 } else if ((!isPowerOf2_32(Width) || Width < 8) &&
185 ST.canUseExtension(
186 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers)) {
187 MIRBuilder.buildInstr(SPIRV::OpExtension)
188 .addImm(SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
189 MIRBuilder.buildInstr(SPIRV::OpCapability)
190 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
191 }
192 return MIRBuilder.buildInstr(SPIRV::OpTypeInt)
193 .addDef(createTypeVReg(MIRBuilder))
194 .addImm(Width)
195 .addImm(IsSigned ? 1 : 0);
196 });
197}
198
199SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
200 MachineIRBuilder &MIRBuilder) {
201 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
202 return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
203 .addDef(createTypeVReg(MIRBuilder))
204 .addImm(Width);
205 });
206}
207
208SPIRVType *
209SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
210 MachineIRBuilder &MIRBuilder,
211 SPIRV::FPEncoding::FPEncoding FPEncode) {
212 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
213 return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
214 .addDef(createTypeVReg(MIRBuilder))
215 .addImm(Width)
216 .addImm(FPEncode);
217 });
218}
219
220SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
221 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
222 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
223 .addDef(createTypeVReg(MIRBuilder));
224 });
225}
226
228 // Other maps that may hold MachineInstr*:
229 // - VRegToTypeMap: We cannot remove the definitions of `MI` from
230 // VRegToTypeMap because some calls to invalidateMachineInstr are replacing MI
231 // with another instruction defining the same register. We expect that if MI
232 // is a type instruction, and it is still referenced in VRegToTypeMap, then
233 // those registers are dead or the VRegToTypeMap is out-of-date. We do not
234 // expect passes to ask for the SPIR-V type of a dead register. If the
235 // VRegToTypeMap is out-of-date already, then there was an error before. We
236 // cannot add an assert to verify this because the VRegToTypeMap can be
237 // out-of-date.
238 // - FunctionToInstr & FunctionToInstrRev: At this point, we should not be
239 // deleting functions. No need to update.
240 // - AliasInstMDMap: Would require a linear search, and the Intel Alias
241 // instruction are not instructions instruction selection will be able to
242 // remove.
243
244 const SPIRVSubtarget &ST = MI->getMF()->getSubtarget<SPIRVSubtarget>();
245 [[maybe_unused]] const SPIRVInstrInfo *TII = ST.getInstrInfo();
246 assert(!TII->isAliasingInstr(*MI) &&
247 "Cannot invalidate aliasing instructions.");
248 assert(MI->getOpcode() != SPIRV::OpFunction &&
249 "Cannot invalidate OpFunction.");
250
251 if (MI->getOpcode() == SPIRV::OpFunctionCall) {
252 if (const auto *F = dyn_cast<Function>(MI->getOperand(2).getGlobal())) {
253 auto It = ForwardCalls.find(F);
254 if (It != ForwardCalls.end()) {
255 It->second.erase(MI);
256 if (It->second.empty())
257 ForwardCalls.erase(It);
258 }
259 }
260 }
261
262 const MachineFunction *MF = MI->getMF();
263 auto It = LastInsertedTypeMap.find(MF);
264 if (It != LastInsertedTypeMap.end() && It->second == MI)
265 LastInsertedTypeMap.erase(MF);
266 // remove from the duplicate tracker to avoid incorrect reuse
267 erase(MI);
268}
269
270SPIRVType *SPIRVGlobalRegistry::createOpType(
271 MachineIRBuilder &MIRBuilder,
272 std::function<MachineInstr *(MachineIRBuilder &)> Op) {
273 auto oldInsertPoint = MIRBuilder.getInsertPt();
274 MachineBasicBlock *OldMBB = &MIRBuilder.getMBB();
275 MachineBasicBlock *NewMBB = &*MIRBuilder.getMF().begin();
276
277 auto LastInsertedType = LastInsertedTypeMap.find(CurMF);
278 if (LastInsertedType != LastInsertedTypeMap.end()) {
279 auto It = LastInsertedType->second->getIterator();
280 // It might happen that this instruction was removed from the first MBB,
281 // hence the Parent's check.
283 if (It->getParent() != NewMBB)
284 InsertAt = oldInsertPoint->getParent() == NewMBB
285 ? oldInsertPoint
286 : getInsertPtValidEnd(NewMBB);
287 else if (It->getNextNode())
288 InsertAt = It->getNextNode()->getIterator();
289 else
290 InsertAt = getInsertPtValidEnd(NewMBB);
291 MIRBuilder.setInsertPt(*NewMBB, InsertAt);
292 } else {
293 MIRBuilder.setInsertPt(*NewMBB, NewMBB->begin());
294 auto Result = LastInsertedTypeMap.try_emplace(CurMF, nullptr);
295 assert(Result.second);
296 LastInsertedType = Result.first;
297 }
298
299 MachineInstr *Type = Op(MIRBuilder);
300 // We expect all users of this function to insert definitions at the insertion
301 // point set above that is always the first MBB.
302 assert(Type->getParent() == NewMBB);
303 LastInsertedType->second = Type;
304
305 MIRBuilder.setInsertPt(*OldMBB, oldInsertPoint);
306 return Type;
307}
308
309SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
310 SPIRVType *ElemType,
311 MachineIRBuilder &MIRBuilder) {
312 auto EleOpc = ElemType->getOpcode();
313 (void)EleOpc;
314 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
315 EleOpc == SPIRV::OpTypeBool) &&
316 "Invalid vector element type");
317
318 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
319 return MIRBuilder.buildInstr(SPIRV::OpTypeVector)
320 .addDef(createTypeVReg(MIRBuilder))
321 .addUse(getSPIRVTypeID(ElemType))
322 .addImm(NumElems);
323 });
324}
325
327 SPIRVType *SpvType,
328 const SPIRVInstrInfo &TII,
329 bool ZeroAsNull) {
330 LLVMContext &Ctx = CurMF->getFunction().getContext();
331 auto *const CF = ConstantFP::get(Ctx, Val);
332 const MachineInstr *MI = findMI(CF, CurMF);
333 if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
334 MI->getOpcode() == SPIRV::OpConstantF))
335 return MI->getOperand(0).getReg();
336 return createConstFP(CF, I, SpvType, TII, ZeroAsNull);
337}
338
340 MachineInstr &I, SPIRVType *SpvType,
341 const SPIRVInstrInfo &TII,
342 bool ZeroAsNull) {
343 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
344 LLT LLTy = LLT::scalar(BitWidth);
345 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
346 CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
347 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
348
349 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
350 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
351 SPIRVType *NewType =
352 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
354 // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
355 if (CF->getValue().isPosZero() && ZeroAsNull) {
356 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
357 .addDef(Res)
358 .addUse(getSPIRVTypeID(SpvType));
359 } else {
360 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
361 .addDef(Res)
362 .addUse(getSPIRVTypeID(SpvType));
365 MIB);
366 }
367 const auto &ST = CurMF->getSubtarget();
368 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
369 *ST.getRegisterInfo(),
370 *ST.getRegBankInfo());
371 return MIB;
372 });
373 add(CF, NewType);
374 return Res;
375}
376
378 SPIRVType *SpvType,
379 const SPIRVInstrInfo &TII,
380 bool ZeroAsNull) {
382 auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);
383 const MachineInstr *MI = findMI(CI, CurMF);
384 if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||
385 MI->getOpcode() == SPIRV::OpConstantI))
386 return MI->getOperand(0).getReg();
387 return createConstInt(CI, I, SpvType, TII, ZeroAsNull);
388}
389
392 SPIRVType *SpvType,
393 const SPIRVInstrInfo &TII,
394 bool ZeroAsNull) {
395 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
396 LLT LLTy = LLT::scalar(BitWidth);
397 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
398 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
400
401 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
402 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
403 SPIRVType *NewType =
404 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
406 if (BitWidth == 1) {
407 MIB = MIRBuilder
408 .buildInstr(CI->isZero() ? SPIRV::OpConstantFalse
409 : SPIRV::OpConstantTrue)
410 .addDef(Res)
411 .addUse(getSPIRVTypeID(SpvType));
412 } else if (!CI->isZero() || !ZeroAsNull) {
413 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
414 .addDef(Res)
415 .addUse(getSPIRVTypeID(SpvType));
416 addNumImm(CI->getValue(), MIB);
417 } else {
418 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
419 .addDef(Res)
420 .addUse(getSPIRVTypeID(SpvType));
421 }
422 const auto &ST = CurMF->getSubtarget();
423 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
424 *ST.getRegisterInfo(),
425 *ST.getRegBankInfo());
426 return MIB;
427 });
428 add(CI, NewType);
429 return Res;
430}
431
433 MachineIRBuilder &MIRBuilder,
434 SPIRVType *SpvType, bool EmitIR,
435 bool ZeroAsNull) {
436 assert(SpvType);
437 auto &MF = MIRBuilder.getMF();
439 // TODO: Avoid implicit trunc?
440 // See https://github.com/llvm/llvm-project/issues/112510.
441 auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val,
442 /*IsSigned=*/false, /*ImplicitTrunc=*/true);
443 Register Res = find(CI, &MF);
444 if (Res.isValid())
445 return Res;
446
447 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
448 LLT LLTy = LLT::scalar(BitWidth);
449 MachineRegisterInfo &MRI = MF.getRegInfo();
450 Res = MRI.createGenericVirtualRegister(LLTy);
451 MRI.setRegClass(Res, &SPIRV::iIDRegClass);
452 assignTypeToVReg(Ty, Res, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
453 EmitIR);
454
455 SPIRVType *NewType =
456 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
457 if (EmitIR)
458 return MIRBuilder.buildConstant(Res, *CI);
459 Register SpvTypeReg = getSPIRVTypeID(SpvType);
461 if (Val || !ZeroAsNull) {
462 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
463 .addDef(Res)
464 .addUse(SpvTypeReg);
465 addNumImm(APInt(BitWidth, Val), MIB);
466 } else {
467 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
468 .addDef(Res)
469 .addUse(SpvTypeReg);
470 }
471 const auto &Subtarget = CurMF->getSubtarget();
472 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
473 *Subtarget.getRegisterInfo(),
474 *Subtarget.getRegBankInfo());
475 return MIB;
476 });
477 add(CI, NewType);
478 return Res;
479}
480
482 MachineIRBuilder &MIRBuilder,
483 SPIRVType *SpvType) {
484 auto &MF = MIRBuilder.getMF();
485 LLVMContext &Ctx = MF.getFunction().getContext();
486 if (!SpvType)
487 SpvType = getOrCreateSPIRVType(Type::getFloatTy(Ctx), MIRBuilder,
488 SPIRV::AccessQualifier::ReadWrite, true);
489 auto *const CF = ConstantFP::get(Ctx, Val);
490 Register Res = find(CF, &MF);
491 if (Res.isValid())
492 return Res;
493
495 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
496 MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
497 assignSPIRVTypeToVReg(SpvType, Res, MF);
498
499 SPIRVType *NewType =
500 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
502 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
503 .addDef(Res)
504 .addUse(getSPIRVTypeID(SpvType));
505 addNumImm(CF->getValueAPF().bitcastToAPInt(), MIB);
506 return MIB;
507 });
508 add(CF, NewType);
509 return Res;
510}
511
512Register SPIRVGlobalRegistry::getOrCreateBaseRegister(
513 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
514 const SPIRVInstrInfo &TII, unsigned BitWidth, bool ZeroAsNull) {
515 SPIRVType *Type = SpvType;
516 if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
517 SpvType->getOpcode() == SPIRV::OpTypeArray) {
518 auto EleTypeReg = SpvType->getOperand(1).getReg();
519 Type = getSPIRVTypeForVReg(EleTypeReg);
520 }
521 if (Type->getOpcode() == SPIRV::OpTypeFloat) {
523 return getOrCreateConstFP(cast<ConstantFP>(Val)->getValue(), I, SpvBaseType,
524 TII, ZeroAsNull);
525 }
526 assert(Type->getOpcode() == SPIRV::OpTypeInt);
529 SpvBaseType, TII, ZeroAsNull);
530}
531
532Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
533 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
534 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
535 unsigned ElemCnt, bool ZeroAsNull) {
536 if (Register R = find(CA, CurMF); R.isValid())
537 return R;
538
539 bool IsNull = Val->isNullValue() && ZeroAsNull;
540 Register ElemReg;
541 if (!IsNull)
542 ElemReg =
543 getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
544
545 LLT LLTy = LLT::scalar(64);
546 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
547 CurMF->getRegInfo().setRegClass(Res, getRegClass(SpvType));
548 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
549
550 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
551 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
552 const MachineInstr *NewMI =
553 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
554 MachineInstrBuilder MIB;
555 if (!IsNull) {
556 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
557 .addDef(Res)
558 .addUse(getSPIRVTypeID(SpvType));
559 for (unsigned i = 0; i < ElemCnt; ++i)
560 MIB.addUse(ElemReg);
561 } else {
562 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
563 .addDef(Res)
564 .addUse(getSPIRVTypeID(SpvType));
565 }
566 const auto &Subtarget = CurMF->getSubtarget();
567 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
568 *Subtarget.getRegisterInfo(),
569 *Subtarget.getRegBankInfo());
570 return MIB;
571 });
572 add(CA, NewMI);
573 return Res;
574}
575
578 SPIRVType *SpvType,
579 const SPIRVInstrInfo &TII,
580 bool ZeroAsNull) {
581 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
582 assert(LLVMTy->isVectorTy());
583 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
584 Type *LLVMBaseTy = LLVMVecTy->getElementType();
585 assert(LLVMBaseTy->isIntegerTy());
586 auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
587 auto *ConstVec =
588 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
589 unsigned BW = getScalarOrVectorBitWidth(SpvType);
590 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
591 SpvType->getOperand(2).getImm(),
592 ZeroAsNull);
593}
594
597 SPIRVType *SpvType,
598 const SPIRVInstrInfo &TII,
599 bool ZeroAsNull) {
600 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
601 assert(LLVMTy->isVectorTy());
602 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
603 Type *LLVMBaseTy = LLVMVecTy->getElementType();
604 assert(LLVMBaseTy->isFloatingPointTy());
605 auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
606 auto *ConstVec =
607 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
608 unsigned BW = getScalarOrVectorBitWidth(SpvType);
609 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
610 SpvType->getOperand(2).getImm(),
611 ZeroAsNull);
612}
613
615 uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,
616 const SPIRVInstrInfo &TII) {
617 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
618 assert(LLVMTy->isArrayTy());
619 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
620 Type *LLVMBaseTy = LLVMArrTy->getElementType();
621 Constant *CI = ConstantInt::get(LLVMBaseTy, Val);
622 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
623 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
624 // The following is reasonably unique key that is better that [Val]. The naive
625 // alternative would be something along the lines of:
626 // SmallVector<Constant *> NumCI(Num, CI);
627 // Constant *UniqueKey =
628 // ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);
629 // that would be a truly unique but dangerous key, because it could lead to
630 // the creation of constants of arbitrary length (that is, the parameter of
631 // memset) which were missing in the original module.
633 {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),
634 ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});
635 return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,
636 LLVMArrTy->getNumElements());
637}
638
639Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
640 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
641 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
642 if (Register R = find(CA, CurMF); R.isValid())
643 return R;
644
645 Register ElemReg;
646 if (Val || EmitIR) {
647 SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
648 ElemReg = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
649 }
650 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);
651 Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
652 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
653 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
654
655 const MachineInstr *NewMI =
656 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
657 if (EmitIR)
658 return MIRBuilder.buildSplatBuildVector(Res, ElemReg);
659
660 if (Val) {
661 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
662 .addDef(Res)
663 .addUse(getSPIRVTypeID(SpvType));
664 for (unsigned i = 0; i < ElemCnt; ++i)
665 MIB.addUse(ElemReg);
666 return MIB;
667 }
668
669 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
670 .addDef(Res)
671 .addUse(getSPIRVTypeID(SpvType));
672 });
673 add(CA, NewMI);
674 return Res;
675}
676
679 MachineIRBuilder &MIRBuilder,
680 SPIRVType *SpvType, bool EmitIR) {
681 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
682 assert(LLVMTy->isVectorTy());
683 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
684 Type *LLVMBaseTy = LLVMVecTy->getElementType();
685 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
686 auto ConstVec =
687 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
688 unsigned BW = getScalarOrVectorBitWidth(SpvType);
689 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
690 ConstVec, BW,
691 SpvType->getOperand(2).getImm());
692}
693
696 SPIRVType *SpvType) {
697 const Type *Ty = getTypeForSPIRVType(SpvType);
698 unsigned AddressSpace = typeToAddressSpace(Ty);
699 Type *ElemTy = ::getPointeeType(Ty);
700 assert(ElemTy);
703 Register Res = find(CP, CurMF);
704 if (Res.isValid())
705 return Res;
706
707 LLT LLTy = LLT::pointer(AddressSpace, PointerSize);
708 Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
709 CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);
710 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
711
712 const MachineInstr *NewMI =
713 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
714 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
715 .addDef(Res)
716 .addUse(getSPIRVTypeID(SpvType));
717 });
718 add(CP, NewMI);
719 return Res;
720}
721
724 unsigned Param, unsigned FilerMode,
725 MachineIRBuilder &MIRBuilder) {
726 auto Sampler =
727 ResReg.isValid()
728 ? ResReg
729 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
730 SPIRVType *TypeSampler = getOrCreateOpTypeSampler(MIRBuilder);
731 Register TypeSamplerReg = getSPIRVTypeID(TypeSampler);
732 // We cannot use createOpType() logic here, because of the
733 // GlobalISel/IRTranslator.cpp check for a tail call that expects that
734 // MIRBuilder.getInsertPt() has a previous instruction. If this constant is
735 // inserted as a result of "__translate_sampler_initializer()" this would
736 // break this IRTranslator assumption.
737 MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
738 .addDef(Sampler)
739 .addUse(TypeSamplerReg)
741 .addImm(Param)
742 .addImm(FilerMode);
743 return Sampler;
744}
745
747 Register ResVReg, SPIRVType *BaseType, StringRef Name,
748 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
749 const MachineInstr *Init, bool IsConst,
750 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageType,
751 MachineIRBuilder &MIRBuilder, bool IsInstSelector) {
752 const GlobalVariable *GVar = nullptr;
753 if (GV) {
755 } else {
756 // If GV is not passed explicitly, use the name to find or construct
757 // the global variable.
758 Module *M = MIRBuilder.getMF().getFunction().getParent();
759 GVar = M->getGlobalVariable(Name);
760 if (GVar == nullptr) {
761 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
762 // Module takes ownership of the global var.
763 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
765 Twine(Name));
766 }
767 GV = GVar;
768 }
769
770 const MachineFunction *MF = &MIRBuilder.getMF();
771 Register Reg = find(GVar, MF);
772 if (Reg.isValid()) {
773 if (Reg != ResVReg)
774 MIRBuilder.buildCopy(ResVReg, Reg);
775 return ResVReg;
776 }
777
778 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
779 .addDef(ResVReg)
781 .addImm(static_cast<uint32_t>(Storage));
782 if (Init)
783 MIB.addUse(Init->getOperand(0).getReg());
784 // ISel may introduce a new register on this step, so we need to add it to
785 // DT and correct its type avoiding fails on the next stage.
786 if (IsInstSelector) {
787 const auto &Subtarget = CurMF->getSubtarget();
788 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
789 *Subtarget.getRegisterInfo(),
790 *Subtarget.getRegBankInfo());
791 }
792 add(GVar, MIB);
793
794 Reg = MIB->getOperand(0).getReg();
795 addGlobalObject(GVar, MF, Reg);
796
797 // Set to Reg the same type as ResVReg has.
798 auto MRI = MIRBuilder.getMRI();
799 if (Reg != ResVReg) {
800 LLT RegLLTy =
801 LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
802 MRI->setType(Reg, RegLLTy);
803 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
804 } else {
805 // Our knowledge about the type may be updated.
806 // If that's the case, we need to update a type
807 // associated with the register.
808 SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
809 if (!DefType || DefType != BaseType)
810 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
811 }
812
813 // If it's a global variable with name, output OpName for it.
814 if (GVar && GVar->hasName())
815 buildOpName(Reg, GVar->getName(), MIRBuilder);
816
817 // Output decorations for the GV.
818 // TODO: maybe move to GenerateDecorations pass.
819 const SPIRVSubtarget &ST =
821 if (IsConst && !ST.isShader())
822 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
823
824 if (GVar && GVar->getAlign().valueOrOne().value() != 1 && !ST.isShader()) {
825 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
826 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
827 }
828
829 if (LinkageType)
830 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
831 {static_cast<uint32_t>(*LinkageType)}, Name);
832
833 SPIRV::BuiltIn::BuiltIn BuiltInId;
834 if (getSpirvBuiltInIdByName(Name, BuiltInId))
835 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
836 {static_cast<uint32_t>(BuiltInId)});
837
838 // If it's a global variable with "spirv.Decorations" metadata node
839 // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
840 // arguments.
841 MDNode *GVarMD = nullptr;
842 if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
843 buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD, ST);
844
845 return Reg;
846}
847
848// Returns a name based on the Type. Notes that this does not look at
849// decorations, and will return the same string for two types that are the same
850// except for decorations.
852 const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name,
853 MachineIRBuilder &MIRBuilder) {
854 Register VarReg =
855 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
856
857 buildGlobalVariable(VarReg, VarType, Name, nullptr,
858 getPointerStorageClass(VarType), nullptr, false,
859 std::nullopt, MIRBuilder, false);
860
861 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::DescriptorSet, {Set});
862 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::Binding, {Binding});
863 return VarReg;
864}
865
866// TODO: Double check the calls to getOpTypeArray to make sure that `ElemType`
867// is explicitly laid out when required.
868SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
869 SPIRVType *ElemType,
870 MachineIRBuilder &MIRBuilder,
871 bool ExplicitLayoutRequired,
872 bool EmitIR) {
873 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
874 "Invalid array element type");
875 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
876 SPIRVType *ArrayType = nullptr;
877 const SPIRVSubtarget &ST =
879 if (NumElems != 0) {
880 Register NumElementsVReg =
881 buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);
882 ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
883 return MIRBuilder.buildInstr(SPIRV::OpTypeArray)
884 .addDef(createTypeVReg(MIRBuilder))
885 .addUse(getSPIRVTypeID(ElemType))
886 .addUse(NumElementsVReg);
887 });
888 } else {
889 if (!ST.isShader()) {
891 "Runtime arrays are not allowed in non-shader "
892 "SPIR-V modules");
893 return nullptr;
894 }
895 ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
896 return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)
897 .addDef(createTypeVReg(MIRBuilder))
898 .addUse(getSPIRVTypeID(ElemType));
899 });
900 }
901
902 if (ExplicitLayoutRequired && !isResourceType(ElemType)) {
903 Type *ET = const_cast<Type *>(getTypeForSPIRVType(ElemType));
904 addArrayStrideDecorations(ArrayType->defs().begin()->getReg(), ET,
905 MIRBuilder);
906 }
907
908 return ArrayType;
909}
910
911SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
912 MachineIRBuilder &MIRBuilder) {
913 assert(Ty->hasName());
914 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
915 Register ResVReg = createTypeVReg(MIRBuilder);
916 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
917 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
918 addStringImm(Name, MIB);
919 buildOpName(ResVReg, Name, MIRBuilder);
920 return MIB;
921 });
922}
923
924SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
925 const StructType *Ty, MachineIRBuilder &MIRBuilder,
926 SPIRV::AccessQualifier::AccessQualifier AccQual,
927 StructOffsetDecorator Decorator, bool EmitIR) {
928 Type *OriginalElementType = nullptr;
929 uint64_t TotalSize = 0;
930 if (matchPeeledArrayPattern(Ty, OriginalElementType, TotalSize)) {
931 SPIRVType *ElementSPIRVType = findSPIRVType(
932 OriginalElementType, MIRBuilder, AccQual,
933 /* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);
934 return getOpTypeArray(TotalSize, ElementSPIRVType, MIRBuilder,
935 /*ExplicitLayoutRequired=*/Decorator != nullptr,
936 EmitIR);
937 }
938
939 const SPIRVSubtarget &ST =
941 SmallVector<Register, 4> FieldTypes;
942 constexpr unsigned MaxWordCount = UINT16_MAX;
943 const size_t NumElements = Ty->getNumElements();
944
945 size_t MaxNumElements = MaxWordCount - 2;
946 size_t SPIRVStructNumElements = NumElements;
947 if (NumElements > MaxNumElements) {
948 // Do adjustments for continued instructions.
949 SPIRVStructNumElements = MaxNumElements;
950 MaxNumElements = MaxWordCount - 1;
951 }
952
953 for (const auto &Elem : Ty->elements()) {
954 SPIRVType *ElemTy = findSPIRVType(
955 toTypedPointer(Elem), MIRBuilder, AccQual,
956 /* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);
957 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
958 "Invalid struct element type");
959 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
960 }
961 Register ResVReg = createTypeVReg(MIRBuilder);
962 if (Ty->hasName())
963 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
964 if (Ty->isPacked() && !ST.isShader())
965 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
966
967 SPIRVType *SPVType =
968 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
969 auto MIBStruct =
970 MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
971 for (size_t I = 0; I < SPIRVStructNumElements; ++I)
972 MIBStruct.addUse(FieldTypes[I]);
973 for (size_t I = SPIRVStructNumElements; I < NumElements;
974 I += MaxNumElements) {
975 auto MIBCont =
976 MIRBuilder.buildInstr(SPIRV::OpTypeStructContinuedINTEL);
977 for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)
978 MIBCont.addUse(FieldTypes[I]);
979 }
980 return MIBStruct;
981 });
982
983 if (Decorator)
984 Decorator(SPVType->defs().begin()->getReg());
985
986 return SPVType;
987}
988
989SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
990 const Type *Ty, MachineIRBuilder &MIRBuilder,
991 SPIRV::AccessQualifier::AccessQualifier AccQual) {
992 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
993 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
994}
995
996SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
997 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
998 MachineIRBuilder &MIRBuilder, Register Reg) {
999 if (!Reg.isValid())
1000 Reg = createTypeVReg(MIRBuilder);
1001
1002 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1003 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
1004 .addDef(Reg)
1005 .addImm(static_cast<uint32_t>(SC))
1006 .addUse(getSPIRVTypeID(ElemType));
1007 });
1008}
1009
1010SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
1011 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
1012 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1013 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
1014 .addUse(createTypeVReg(MIRBuilder))
1015 .addImm(static_cast<uint32_t>(SC));
1016 });
1017}
1018
1019SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
1020 const FunctionType *Ty, SPIRVType *RetType,
1021 const SmallVectorImpl<SPIRVType *> &ArgTypes,
1022 MachineIRBuilder &MIRBuilder) {
1023 if (Ty->isVarArg()) {
1024 Function &Fn = MIRBuilder.getMF().getFunction();
1025 Ty->getContext().diagnose(DiagnosticInfoUnsupported(
1026 Fn, "SPIR-V does not support variadic functions",
1027 MIRBuilder.getDebugLoc()));
1028 }
1029 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1030 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
1031 .addDef(createTypeVReg(MIRBuilder))
1032 .addUse(getSPIRVTypeID(RetType));
1033 for (const SPIRVType *ArgType : ArgTypes)
1034 MIB.addUse(getSPIRVTypeID(ArgType));
1035 return MIB;
1036 });
1037}
1038
1040 const Type *Ty, SPIRVType *RetType,
1041 const SmallVectorImpl<SPIRVType *> &ArgTypes,
1042 MachineIRBuilder &MIRBuilder) {
1043 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
1044 return MI;
1045 const MachineInstr *NewMI =
1046 getOpTypeFunction(cast<FunctionType>(Ty), RetType, ArgTypes, MIRBuilder);
1047 add(Ty, false, NewMI);
1048 return finishCreatingSPIRVType(Ty, NewMI);
1049}
1050
1051SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
1052 const Type *Ty, MachineIRBuilder &MIRBuilder,
1053 SPIRV::AccessQualifier::AccessQualifier AccQual,
1054 bool ExplicitLayoutRequired, bool EmitIR) {
1055 Ty = adjustIntTypeByWidth(Ty);
1056 // TODO: findMI needs to know if a layout is required.
1057 if (const MachineInstr *MI =
1058 findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))
1059 return MI;
1060 if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end())
1061 return It->second;
1062 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, ExplicitLayoutRequired,
1063 EmitIR);
1064}
1065
1067 assert(SpirvType && "Attempting to get type id for nullptr type.");
1068 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||
1069 SpirvType->getOpcode() == SPIRV::OpTypeStructContinuedINTEL)
1070 return SpirvType->uses().begin()->getReg();
1071 return SpirvType->defs().begin()->getReg();
1072}
1073
1074// We need to use a new LLVM integer type if there is a mismatch between
1075// number of bits in LLVM and SPIRV integer types to let DuplicateTracker
1076// ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without
1077// such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the
1078// same "OpTypeInt 8" type for a series of LLVM integer types with number of
1079// bits less than 8. This would lead to duplicate type definitions
1080// eventually due to the method that DuplicateTracker utilizes to reason
1081// about uniqueness of type records.
1082const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {
1083 if (auto IType = dyn_cast<IntegerType>(Ty)) {
1084 unsigned SrcBitWidth = IType->getBitWidth();
1085 if (SrcBitWidth > 1) {
1086 unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);
1087 // Maybe change source LLVM type to keep DuplicateTracker consistent.
1088 if (SrcBitWidth != BitWidth)
1089 Ty = IntegerType::get(Ty->getContext(), BitWidth);
1090 }
1091 }
1092 return Ty;
1093}
1094
1095SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
1096 const Type *Ty, MachineIRBuilder &MIRBuilder,
1097 SPIRV::AccessQualifier::AccessQualifier AccQual,
1098 bool ExplicitLayoutRequired, bool EmitIR) {
1099 if (isSpecialOpaqueType(Ty))
1100 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
1101
1102 if (const MachineInstr *MI =
1103 findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))
1104 return MI;
1105
1106 if (auto IType = dyn_cast<IntegerType>(Ty)) {
1107 const unsigned Width = IType->getBitWidth();
1108 return Width == 1 ? getOpTypeBool(MIRBuilder)
1109 : getOpTypeInt(Width, MIRBuilder, false);
1110 }
1111 if (Ty->isFloatingPointTy()) {
1112 if (Ty->isBFloatTy()) {
1113 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder,
1114 SPIRV::FPEncoding::BFloat16KHR);
1115 } else {
1116 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
1117 }
1118 }
1119 if (Ty->isVoidTy())
1120 return getOpTypeVoid(MIRBuilder);
1121 if (Ty->isVectorTy()) {
1122 SPIRVType *El =
1123 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder,
1124 AccQual, ExplicitLayoutRequired, EmitIR);
1125 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
1126 MIRBuilder);
1127 }
1128 if (Ty->isArrayTy()) {
1129 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder,
1130 AccQual, ExplicitLayoutRequired, EmitIR);
1131 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder,
1132 ExplicitLayoutRequired, EmitIR);
1133 }
1134 if (auto SType = dyn_cast<StructType>(Ty)) {
1135 if (SType->isOpaque())
1136 return getOpTypeOpaque(SType, MIRBuilder);
1137
1138 StructOffsetDecorator Decorator = nullptr;
1139 if (ExplicitLayoutRequired) {
1140 Decorator = [&MIRBuilder, SType, this](Register Reg) {
1141 addStructOffsetDecorations(Reg, const_cast<StructType *>(SType),
1142 MIRBuilder);
1143 };
1144 }
1145 return getOpTypeStruct(SType, MIRBuilder, AccQual, std::move(Decorator),
1146 EmitIR);
1147 }
1148 if (auto FType = dyn_cast<FunctionType>(Ty)) {
1149 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder,
1150 AccQual, ExplicitLayoutRequired, EmitIR);
1151 SmallVector<SPIRVType *, 4> ParamTypes;
1152 for (const auto &ParamTy : FType->params())
1153 ParamTypes.push_back(findSPIRVType(ParamTy, MIRBuilder, AccQual,
1154 ExplicitLayoutRequired, EmitIR));
1155 return getOpTypeFunction(FType, RetTy, ParamTypes, MIRBuilder);
1156 }
1157
1158 unsigned AddrSpace = typeToAddressSpace(Ty);
1159 SPIRVType *SpvElementType = nullptr;
1160 if (Type *ElemTy = ::getPointeeType(Ty))
1161 SpvElementType = getOrCreateSPIRVType(ElemTy, MIRBuilder, AccQual, EmitIR);
1162 else
1163 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
1164
1165 // Get access to information about available extensions
1166 const SPIRVSubtarget *ST =
1167 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
1168 auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
1169
1170 Type *ElemTy = ::getPointeeType(Ty);
1171 if (!ElemTy) {
1172 ElemTy = Type::getInt8Ty(MIRBuilder.getContext());
1173 }
1174
1175 // If we have forward pointer associated with this type, use its register
1176 // operand to create OpTypePointer.
1177 if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end()) {
1178 Register Reg = getSPIRVTypeID(It->second);
1179 // TODO: what does getOpTypePointer do?
1180 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
1181 }
1182
1183 return getOrCreateSPIRVPointerType(ElemTy, MIRBuilder, SC);
1184}
1185
1186SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
1187 const Type *Ty, MachineIRBuilder &MIRBuilder,
1188 SPIRV::AccessQualifier::AccessQualifier AccessQual,
1189 bool ExplicitLayoutRequired, bool EmitIR) {
1190 // TODO: Could this create a problem if one requires an explicit layout, and
1191 // the next time it does not?
1192 if (TypesInProcessing.count(Ty) && !isPointerTyOrWrapper(Ty))
1193 return nullptr;
1194 TypesInProcessing.insert(Ty);
1195 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual,
1196 ExplicitLayoutRequired, EmitIR);
1197 TypesInProcessing.erase(Ty);
1198 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
1199
1200 // TODO: We could end up with two SPIR-V types pointing to the same llvm type.
1201 // Is that a problem?
1202 SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
1203
1204 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||
1205 findMI(Ty, false, &MIRBuilder.getMF()) || isSpecialOpaqueType(Ty))
1206 return SpirvType;
1207
1208 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1209 ExtTy && isTypedPointerWrapper(ExtTy))
1210 add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), SpirvType);
1211 else if (!isPointerTy(Ty))
1212 add(Ty, ExplicitLayoutRequired, SpirvType);
1213 else if (isTypedPointerTy(Ty))
1214 add(cast<TypedPointerType>(Ty)->getElementType(),
1215 getPointerAddressSpace(Ty), SpirvType);
1216 else
1218 getPointerAddressSpace(Ty), SpirvType);
1219 return SpirvType;
1220}
1221
1222SPIRVType *
1224 const MachineFunction *MF) const {
1225 auto t = VRegToTypeMap.find(MF ? MF : CurMF);
1226 if (t != VRegToTypeMap.end()) {
1227 auto tt = t->second.find(VReg);
1228 if (tt != t->second.end())
1229 return tt->second;
1230 }
1231 return nullptr;
1232}
1233
1235 MachineFunction *MF) {
1236 if (!MF)
1237 MF = CurMF;
1238 MachineInstr *Instr = getVRegDef(MF->getRegInfo(), VReg);
1239 return getSPIRVTypeForVReg(Instr->getOperand(1).getReg(), MF);
1240}
1241
1243 const Type *Ty, MachineIRBuilder &MIRBuilder,
1244 SPIRV::AccessQualifier::AccessQualifier AccessQual,
1245 bool ExplicitLayoutRequired, bool EmitIR) {
1246 const MachineFunction *MF = &MIRBuilder.getMF();
1247 Register Reg;
1248 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1249 ExtTy && isTypedPointerWrapper(ExtTy))
1250 Reg = find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), MF);
1251 else if (!isPointerTy(Ty))
1252 Reg = find(Ty = adjustIntTypeByWidth(Ty), ExplicitLayoutRequired, MF);
1253 else if (isTypedPointerTy(Ty))
1254 Reg = find(cast<TypedPointerType>(Ty)->getElementType(),
1255 getPointerAddressSpace(Ty), MF);
1256 else
1257 Reg = find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
1258 getPointerAddressSpace(Ty), MF);
1259 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
1260 return getSPIRVTypeForVReg(Reg);
1261
1262 TypesInProcessing.clear();
1263 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual,
1264 ExplicitLayoutRequired, EmitIR);
1265 // Create normal pointer types for the corresponding OpTypeForwardPointers.
1266 for (auto &CU : ForwardPointerTypes) {
1267 // Pointer type themselves do not require an explicit layout. The types
1268 // they pointer to might, but that is taken care of when creating the type.
1269 bool PtrNeedsLayout = false;
1270 const Type *Ty2 = CU.first;
1271 SPIRVType *STy2 = CU.second;
1272 if ((Reg = find(Ty2, PtrNeedsLayout, MF)).isValid())
1273 STy2 = getSPIRVTypeForVReg(Reg);
1274 else
1275 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, PtrNeedsLayout,
1276 EmitIR);
1277 if (Ty == Ty2)
1278 STy = STy2;
1279 }
1280 ForwardPointerTypes.clear();
1281 return STy;
1282}
1283
1285 unsigned TypeOpcode) const {
1287 assert(Type && "isScalarOfType VReg has no type assigned");
1288 return Type->getOpcode() == TypeOpcode;
1289}
1290
1292 unsigned TypeOpcode) const {
1294 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
1295 if (Type->getOpcode() == TypeOpcode)
1296 return true;
1297 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1298 Register ScalarTypeVReg = Type->getOperand(1).getReg();
1299 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
1300 return ScalarType->getOpcode() == TypeOpcode;
1301 }
1302 return false;
1303}
1304
1306 switch (Type->getOpcode()) {
1307 case SPIRV::OpTypeImage:
1308 case SPIRV::OpTypeSampler:
1309 case SPIRV::OpTypeSampledImage:
1310 return true;
1311 case SPIRV::OpTypeStruct:
1312 return hasBlockDecoration(Type);
1313 default:
1314 return false;
1315 }
1316 return false;
1317}
1318unsigned
1322
1323unsigned
1325 if (!Type)
1326 return 0;
1327 return Type->getOpcode() == SPIRV::OpTypeVector
1328 ? static_cast<unsigned>(Type->getOperand(2).getImm())
1329 : 1;
1330}
1331
1332SPIRVType *
1336
1337SPIRVType *
1339 if (!Type)
1340 return nullptr;
1341 Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector
1342 ? Type->getOperand(1).getReg()
1343 : Type->getOperand(0).getReg();
1344 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);
1345 assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),
1346 ScalarType->getOpcode()));
1347 return ScalarType;
1348}
1349
1350unsigned
1352 assert(Type && "Invalid Type pointer");
1353 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1354 auto EleTypeReg = Type->getOperand(1).getReg();
1355 Type = getSPIRVTypeForVReg(EleTypeReg);
1356 }
1357 if (Type->getOpcode() == SPIRV::OpTypeInt ||
1358 Type->getOpcode() == SPIRV::OpTypeFloat)
1359 return Type->getOperand(1).getImm();
1360 if (Type->getOpcode() == SPIRV::OpTypeBool)
1361 return 1;
1362 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
1363}
1364
1366 const SPIRVType *Type) const {
1367 assert(Type && "Invalid Type pointer");
1368 unsigned NumElements = 1;
1369 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1370 NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1371 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1372 }
1373 return Type->getOpcode() == SPIRV::OpTypeInt ||
1374 Type->getOpcode() == SPIRV::OpTypeFloat
1375 ? NumElements * Type->getOperand(1).getImm()
1376 : 0;
1377}
1378
1380 const SPIRVType *Type) const {
1381 if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1382 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1383 return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1384}
1385
1388 return IntType && IntType->getOperand(2).getImm() != 0;
1389}
1390
1392 return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1393 ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1394 : nullptr;
1395}
1396
1398 SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));
1399 return ElemType ? ElemType->getOpcode() : 0;
1400}
1401
1403 const SPIRVType *Type2) const {
1404 if (!Type1 || !Type2)
1405 return false;
1406 auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1407 // Ignore difference between <1.5 and >=1.5 protocol versions:
1408 // it's valid if either Result Type or Operand is a pointer, and the other
1409 // is a pointer, an integer scalar, or an integer vector.
1410 if (Op1 == SPIRV::OpTypePointer &&
1411 (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1412 return true;
1413 if (Op2 == SPIRV::OpTypePointer &&
1414 (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1415 return true;
1416 unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1417 Bits2 = getNumScalarOrVectorTotalBitWidth(Type2);
1418 return Bits1 > 0 && Bits1 == Bits2;
1419}
1420
1421SPIRV::StorageClass::StorageClass
1424 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
1425 Type->getOperand(1).isImm() && "Pointer type is expected");
1427}
1428
1429SPIRV::StorageClass::StorageClass
1431 return static_cast<SPIRV::StorageClass::StorageClass>(
1432 Type->getOperand(1).getImm());
1433}
1434
1436 MachineIRBuilder &MIRBuilder, Type *ElemType,
1437 SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr) {
1438 auto Key = SPIRV::irhandle_vkbuffer(ElemType, SC, IsWritable);
1439 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1440 return MI;
1441
1442 bool ExplicitLayoutRequired = storageClassRequiresExplictLayout(SC);
1443 // We need to get the SPIR-V type for the element here, so we can add the
1444 // decoration to it.
1445 auto *T = StructType::create(ElemType);
1446 auto *BlockType =
1447 getOrCreateSPIRVType(T, MIRBuilder, SPIRV::AccessQualifier::None,
1448 ExplicitLayoutRequired, EmitIr);
1449
1450 buildOpDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,
1451 SPIRV::Decoration::Block, {});
1452
1453 if (!IsWritable) {
1454 buildOpMemberDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,
1455 SPIRV::Decoration::NonWritable, 0, {});
1456 }
1457
1458 SPIRVType *R = getOrCreateSPIRVPointerTypeInternal(BlockType, MIRBuilder, SC);
1459 add(Key, R);
1460 return R;
1461}
1462
1463SPIRVType *
1466 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1467 return MI;
1468 auto *T = Type::getInt8Ty(MIRBuilder.getContext());
1469 SPIRVType *R = getOrCreateSPIRVIntegerType(8, MIRBuilder);
1470 finishCreatingSPIRVType(T, R);
1471 add(Key, R);
1472 return R;
1473}
1474
1476 MachineIRBuilder &MIRBuilder, Type *T) {
1477 const auto SC = SPIRV::StorageClass::PushConstant;
1478
1479 auto Key = SPIRV::irhandle_vkbuffer(T, SC, /* IsWritable= */ false);
1480 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1481 return MI;
1482
1483 // We need to get the SPIR-V type for the element here, so we can add the
1484 // decoration to it.
1485 auto *BlockType = getOrCreateSPIRVType(
1486 T, MIRBuilder, SPIRV::AccessQualifier::None,
1487 /* ExplicitLayoutRequired= */ true, /* EmitIr= */ false);
1488
1489 buildOpDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,
1490 SPIRV::Decoration::Block, {});
1491 SPIRVType *R = BlockType;
1492 add(Key, R);
1493 return R;
1494}
1495
1497 MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr) {
1498 auto Key = SPIRV::handle(T);
1499 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1500 return MI;
1501
1502 StructType *ST = cast<StructType>(T->getTypeParameter(0));
1503 ArrayRef<uint32_t> Offsets = T->int_params().slice(1);
1504 assert(ST->getNumElements() == Offsets.size());
1505
1506 StructOffsetDecorator Decorator = [&MIRBuilder, &Offsets](Register Reg) {
1507 for (uint32_t I = 0; I < Offsets.size(); ++I) {
1508 buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
1509 {Offsets[I]});
1510 }
1511 };
1512
1513 // We need a new OpTypeStruct instruction because decorations will be
1514 // different from a struct with an explicit layout created from a different
1515 // entry point.
1516 SPIRVType *SPIRVStructType =
1517 getOpTypeStruct(ST, MIRBuilder, SPIRV::AccessQualifier::None,
1518 std::move(Decorator), EmitIr);
1519 add(Key, SPIRVStructType);
1520 return SPIRVStructType;
1521}
1522
1524 const TargetExtType *ExtensionType,
1525 const SPIRV::AccessQualifier::AccessQualifier Qualifier,
1526 MachineIRBuilder &MIRBuilder) {
1527 assert(ExtensionType->getNumTypeParameters() == 1 &&
1528 "SPIR-V image builtin type must have sampled type parameter!");
1529 const SPIRVType *SampledType =
1530 getOrCreateSPIRVType(ExtensionType->getTypeParameter(0), MIRBuilder,
1531 SPIRV::AccessQualifier::ReadWrite, true);
1532 assert((ExtensionType->getNumIntParameters() == 7 ||
1533 ExtensionType->getNumIntParameters() == 6) &&
1534 "Invalid number of parameters for SPIR-V image builtin!");
1535
1536 SPIRV::AccessQualifier::AccessQualifier accessQualifier =
1537 SPIRV::AccessQualifier::None;
1538 if (ExtensionType->getNumIntParameters() == 7) {
1539 accessQualifier = Qualifier == SPIRV::AccessQualifier::WriteOnly
1540 ? SPIRV::AccessQualifier::WriteOnly
1541 : SPIRV::AccessQualifier::AccessQualifier(
1542 ExtensionType->getIntParameter(6));
1543 }
1544
1545 // Create or get an existing type from GlobalRegistry.
1546 SPIRVType *R = getOrCreateOpTypeImage(
1547 MIRBuilder, SampledType,
1548 SPIRV::Dim::Dim(ExtensionType->getIntParameter(0)),
1549 ExtensionType->getIntParameter(1), ExtensionType->getIntParameter(2),
1550 ExtensionType->getIntParameter(3), ExtensionType->getIntParameter(4),
1551 SPIRV::ImageFormat::ImageFormat(ExtensionType->getIntParameter(5)),
1552 accessQualifier);
1553 SPIRVToLLVMType[R] = ExtensionType;
1554 return R;
1555}
1556
1557SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
1558 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1559 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1560 SPIRV::ImageFormat::ImageFormat ImageFormat,
1561 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1562 auto Key = SPIRV::irhandle_image(SPIRVToLLVMType.lookup(SampledType), Dim,
1563 Depth, Arrayed, Multisampled, Sampled,
1564 ImageFormat, AccessQual);
1565 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1566 return MI;
1567 const MachineInstr *NewMI =
1568 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1569 auto MIB =
1570 MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1571 .addDef(createTypeVReg(MIRBuilder))
1572 .addUse(getSPIRVTypeID(SampledType))
1573 .addImm(Dim)
1574 .addImm(Depth) // Depth (whether or not it is a Depth image).
1575 .addImm(Arrayed) // Arrayed.
1576 .addImm(Multisampled) // Multisampled (0 = only single-sample).
1577 .addImm(Sampled) // Sampled (0 = usage known at runtime).
1578 .addImm(ImageFormat);
1579 if (AccessQual != SPIRV::AccessQualifier::None)
1580 MIB.addImm(AccessQual);
1581 return MIB;
1582 });
1583 add(Key, NewMI);
1584 return NewMI;
1585}
1586
1587SPIRVType *
1590 const MachineFunction *MF = &MIRBuilder.getMF();
1591 if (const MachineInstr *MI = findMI(Key, MF))
1592 return MI;
1593 const MachineInstr *NewMI =
1594 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1595 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler)
1596 .addDef(createTypeVReg(MIRBuilder));
1597 });
1598 add(Key, NewMI);
1599 return NewMI;
1600}
1601
1603 MachineIRBuilder &MIRBuilder,
1604 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1605 auto Key = SPIRV::irhandle_pipe(AccessQual);
1606 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1607 return MI;
1608 const MachineInstr *NewMI =
1609 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1610 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1611 .addDef(createTypeVReg(MIRBuilder))
1612 .addImm(AccessQual);
1613 });
1614 add(Key, NewMI);
1615 return NewMI;
1616}
1617
1619 MachineIRBuilder &MIRBuilder) {
1620 auto Key = SPIRV::irhandle_event();
1621 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1622 return MI;
1623 const MachineInstr *NewMI =
1624 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1625 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent)
1626 .addDef(createTypeVReg(MIRBuilder));
1627 });
1628 add(Key, NewMI);
1629 return NewMI;
1630}
1631
1633 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1635 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1636 ImageType->getOperand(1).getReg())),
1637 ImageType);
1638 if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1639 return MI;
1640 const MachineInstr *NewMI =
1641 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1642 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1643 .addDef(createTypeVReg(MIRBuilder))
1644 .addUse(getSPIRVTypeID(ImageType));
1645 });
1646 add(Key, NewMI);
1647 return NewMI;
1648}
1649
1651 MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
1652 const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
1653 uint32_t Use, bool EmitIR) {
1654 if (const MachineInstr *MI =
1655 findMI(ExtensionType, false, &MIRBuilder.getMF()))
1656 return MI;
1657 const MachineInstr *NewMI =
1658 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1659 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
1660 const Type *ET = getTypeForSPIRVType(ElemType);
1661 if (ET->isIntegerTy() && ET->getIntegerBitWidth() == 4 &&
1663 .canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1664 MIRBuilder.buildInstr(SPIRV::OpCapability)
1665 .addImm(SPIRV::Capability::Int4CooperativeMatrixINTEL);
1666 }
1667 return MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
1668 .addDef(createTypeVReg(MIRBuilder))
1669 .addUse(getSPIRVTypeID(ElemType))
1670 .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, EmitIR))
1671 .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, EmitIR))
1672 .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))
1673 .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));
1674 });
1675 add(ExtensionType, false, NewMI);
1676 return NewMI;
1677}
1678
1680 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1681 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
1682 return MI;
1683 const MachineInstr *NewMI =
1684 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1685 return MIRBuilder.buildInstr(Opcode).addDef(createTypeVReg(MIRBuilder));
1686 });
1687 add(Ty, false, NewMI);
1688 return NewMI;
1689}
1690
1692 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode,
1693 const ArrayRef<MCOperand> Operands) {
1694 if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))
1695 return MI;
1696 Register ResVReg = createTypeVReg(MIRBuilder);
1697 const MachineInstr *NewMI =
1698 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1699 MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::UNKNOWN_type)
1700 .addDef(ResVReg)
1701 .addImm(Opcode);
1702 for (MCOperand Operand : Operands) {
1703 if (Operand.isReg()) {
1704 MIB.addUse(Operand.getReg());
1705 } else if (Operand.isImm()) {
1706 MIB.addImm(Operand.getImm());
1707 }
1708 }
1709 return MIB;
1710 });
1711 add(Ty, false, NewMI);
1712 return NewMI;
1713}
1714
1715// Returns nullptr if unable to recognize SPIRV type name
1717 StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR,
1718 SPIRV::StorageClass::StorageClass SC,
1719 SPIRV::AccessQualifier::AccessQualifier AQ) {
1720 unsigned VecElts = 0;
1721 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1722
1723 // Parse strings representing either a SPIR-V or OpenCL builtin type.
1724 if (hasBuiltinTypePrefix(TypeStr))
1726 TypeStr.str(), MIRBuilder.getContext()),
1727 MIRBuilder, AQ, false, true);
1728
1729 // Parse type name in either "typeN" or "type vector[N]" format, where
1730 // N is the number of elements of the vector.
1731 Type *Ty;
1732
1733 Ty = parseBasicTypeName(TypeStr, Ctx);
1734 if (!Ty)
1735 // Unable to recognize SPIRV type name
1736 return nullptr;
1737
1738 const SPIRVType *SpirvTy =
1739 getOrCreateSPIRVType(Ty, MIRBuilder, AQ, false, true);
1740
1741 // Handle "type*" or "type* vector[N]".
1742 if (TypeStr.consume_front("*"))
1743 SpirvTy = getOrCreateSPIRVPointerType(Ty, MIRBuilder, SC);
1744
1745 // Handle "typeN*" or "type vector[N]*".
1746 bool IsPtrToVec = TypeStr.consume_back("*");
1747
1748 if (TypeStr.consume_front(" vector[")) {
1749 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1750 }
1751 TypeStr.getAsInteger(10, VecElts);
1752 if (VecElts > 0)
1753 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder, EmitIR);
1754
1755 if (IsPtrToVec)
1756 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1757
1758 return SpirvTy;
1759}
1760
1761SPIRVType *
1763 MachineIRBuilder &MIRBuilder) {
1764 return getOrCreateSPIRVType(
1766 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, true);
1767}
1768
1769SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1770 SPIRVType *SpirvType) {
1771 assert(CurMF == SpirvType->getMF());
1772 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1773 SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);
1774 return SpirvType;
1775}
1776
1778 MachineInstr &I,
1779 const SPIRVInstrInfo &TII,
1780 unsigned SPIRVOPcode,
1781 Type *Ty) {
1782 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1783 return MI;
1784 MachineBasicBlock &DepMBB = I.getMF()->front();
1785 MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
1786 const MachineInstr *NewMI =
1787 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1788 auto NewTypeMI = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1789 MIRBuilder.getDL(), TII.get(SPIRVOPcode))
1790 .addDef(createTypeVReg(CurMF->getRegInfo()))
1791 .addImm(BitWidth);
1792 // Don't add Encoding to FP type
1793 if (!Ty->isFloatTy()) {
1794 return NewTypeMI.addImm(0);
1795 } else {
1796 return NewTypeMI;
1797 }
1798 });
1799 add(Ty, false, NewMI);
1800 return finishCreatingSPIRVType(Ty, NewMI);
1801}
1802
1804 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1805 // Maybe adjust bit width to keep DuplicateTracker consistent. Without
1806 // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for
1807 // example, the same "OpTypeInt 8" type for a series of LLVM integer types
1808 // with number of bits less than 8, causing duplicate type definitions.
1809 if (BitWidth > 1)
1810 BitWidth = adjustOpTypeIntWidth(BitWidth);
1811 Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);
1812 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1813}
1814
1816 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1817 LLVMContext &Ctx = CurMF->getFunction().getContext();
1818 Type *LLVMTy;
1819 switch (BitWidth) {
1820 case 16:
1821 LLVMTy = Type::getHalfTy(Ctx);
1822 break;
1823 case 32:
1824 LLVMTy = Type::getFloatTy(Ctx);
1825 break;
1826 case 64:
1827 LLVMTy = Type::getDoubleTy(Ctx);
1828 break;
1829 default:
1830 llvm_unreachable("Bit width is of unexpected size.");
1831 }
1832 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1833}
1834
1835SPIRVType *
1837 bool EmitIR) {
1838 return getOrCreateSPIRVType(
1839 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1840 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);
1841}
1842
1843SPIRVType *
1845 const SPIRVInstrInfo &TII) {
1846 Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);
1847 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1848 return MI;
1849 MachineBasicBlock &DepMBB = I.getMF()->front();
1850 MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
1851 const MachineInstr *NewMI =
1852 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1853 return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1854 MIRBuilder.getDL(), TII.get(SPIRV::OpTypeBool))
1855 .addDef(createTypeVReg(CurMF->getRegInfo()));
1856 });
1857 add(Ty, false, NewMI);
1858 return finishCreatingSPIRVType(Ty, NewMI);
1859}
1860
1862 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder,
1863 bool EmitIR) {
1864 return getOrCreateSPIRVType(
1866 NumElements),
1867 MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);
1868}
1869
1871 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1872 const SPIRVInstrInfo &TII) {
1874 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1875 if (const MachineInstr *MI = findMI(Ty, false, CurMF))
1876 return MI;
1877 MachineInstr *DepMI = const_cast<MachineInstr *>(BaseType);
1878 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
1879 const MachineInstr *NewMI =
1880 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1881 return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1882 MIRBuilder.getDL(), TII.get(SPIRV::OpTypeVector))
1883 .addDef(createTypeVReg(CurMF->getRegInfo()))
1885 .addImm(NumElements);
1886 });
1887 add(Ty, false, NewMI);
1888 return finishCreatingSPIRVType(Ty, NewMI);
1889}
1890
1892 const Type *BaseType, MachineInstr &I,
1893 SPIRV::StorageClass::StorageClass SC) {
1894 MachineIRBuilder MIRBuilder(I);
1895 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1896}
1897
1899 const Type *BaseType, MachineIRBuilder &MIRBuilder,
1900 SPIRV::StorageClass::StorageClass SC) {
1901 // TODO: Need to check if EmitIr should always be true.
1902 SPIRVType *SpirvBaseType = getOrCreateSPIRVType(
1903 BaseType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
1905 assert(SpirvBaseType);
1906 return getOrCreateSPIRVPointerTypeInternal(SpirvBaseType, MIRBuilder, SC);
1907}
1908
1910 SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I) {
1911 [[maybe_unused]] SPIRV::StorageClass::StorageClass OldSC =
1912 getPointerStorageClass(PtrType);
1915
1916 SPIRVType *PointeeType = getPointeeType(PtrType);
1917 MachineIRBuilder MIRBuilder(I);
1918 return getOrCreateSPIRVPointerTypeInternal(PointeeType, MIRBuilder, SC);
1919}
1920
1922 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1923 SPIRV::StorageClass::StorageClass SC) {
1924 const Type *LLVMType = getTypeForSPIRVType(BaseType);
1926 SPIRVType *R = getOrCreateSPIRVPointerType(LLVMType, MIRBuilder, SC);
1927 assert(
1928 getPointeeType(R) == BaseType &&
1929 "The base type was not correctly laid out for the given storage class.");
1930 return R;
1931}
1932
1933SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerTypeInternal(
1934 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1935 SPIRV::StorageClass::StorageClass SC) {
1936 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1938 if (const MachineInstr *MI = findMI(PointerElementType, AddressSpace, CurMF))
1939 return MI;
1940 Type *Ty = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1941 AddressSpace);
1942 const MachineInstr *NewMI =
1943 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1944 return BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1945 MIRBuilder.getDebugLoc(),
1946 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1948 .addImm(static_cast<uint32_t>(SC))
1950 });
1951 add(PointerElementType, AddressSpace, NewMI);
1952 return finishCreatingSPIRVType(Ty, NewMI);
1953}
1954
1956 SPIRVType *SpvType,
1957 const SPIRVInstrInfo &TII) {
1958 UndefValue *UV =
1959 UndefValue::get(const_cast<Type *>(getTypeForSPIRVType(SpvType)));
1960 Register Res = find(UV, CurMF);
1961 if (Res.isValid())
1962 return Res;
1963
1964 LLT LLTy = LLT::scalar(64);
1965 Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
1966 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
1967 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1968
1969 MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);
1970 MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());
1971 const MachineInstr *NewMI =
1972 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1973 auto MIB = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),
1974 MIRBuilder.getDL(), TII.get(SPIRV::OpUndef))
1975 .addDef(Res)
1976 .addUse(getSPIRVTypeID(SpvType));
1977 const auto &ST = CurMF->getSubtarget();
1978 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1979 *ST.getRegisterInfo(),
1980 *ST.getRegBankInfo());
1981 return MIB;
1982 });
1983 add(UV, NewMI);
1984 return Res;
1985}
1986
1987const TargetRegisterClass *
1989 unsigned Opcode = SpvType->getOpcode();
1990 switch (Opcode) {
1991 case SPIRV::OpTypeFloat:
1992 return &SPIRV::fIDRegClass;
1993 case SPIRV::OpTypePointer:
1994 return &SPIRV::pIDRegClass;
1995 case SPIRV::OpTypeVector: {
1996 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
1997 unsigned ElemOpcode = ElemType ? ElemType->getOpcode() : 0;
1998 if (ElemOpcode == SPIRV::OpTypeFloat)
1999 return &SPIRV::vfIDRegClass;
2000 if (ElemOpcode == SPIRV::OpTypePointer)
2001 return &SPIRV::vpIDRegClass;
2002 return &SPIRV::vIDRegClass;
2003 }
2004 }
2005 return &SPIRV::iIDRegClass;
2006}
2007
2008inline unsigned getAS(SPIRVType *SpvType) {
2010 static_cast<SPIRV::StorageClass::StorageClass>(
2011 SpvType->getOperand(1).getImm()));
2012}
2013
2015 unsigned Opcode = SpvType ? SpvType->getOpcode() : 0;
2016 switch (Opcode) {
2017 case SPIRV::OpTypeInt:
2018 case SPIRV::OpTypeFloat:
2019 case SPIRV::OpTypeBool:
2020 return LLT::scalar(getScalarOrVectorBitWidth(SpvType));
2021 case SPIRV::OpTypePointer:
2022 return LLT::pointer(getAS(SpvType), getPointerSize());
2023 case SPIRV::OpTypeVector: {
2024 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
2025 LLT ET;
2026 switch (ElemType ? ElemType->getOpcode() : 0) {
2027 case SPIRV::OpTypePointer:
2028 ET = LLT::pointer(getAS(ElemType), getPointerSize());
2029 break;
2030 case SPIRV::OpTypeInt:
2031 case SPIRV::OpTypeFloat:
2032 case SPIRV::OpTypeBool:
2033 ET = LLT::scalar(getScalarOrVectorBitWidth(ElemType));
2034 break;
2035 default:
2036 ET = LLT::scalar(64);
2037 }
2038 return LLT::fixed_vector(
2039 static_cast<unsigned>(SpvType->getOperand(2).getImm()), ET);
2040 }
2041 }
2042 return LLT::scalar(64);
2043}
2044
2045// Aliasing list MD contains several scope MD nodes whithin it. Each scope MD
2046// has a selfreference and an extra MD node for aliasing domain and also it
2047// can contain an optional string operand. Domain MD contains a self-reference
2048// with an optional string operand. Here we unfold the list, creating SPIR-V
2049// aliasing instructions.
2050// TODO: add support for an optional string operand.
2052 MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD) {
2053 if (AliasingListMD->getNumOperands() == 0)
2054 return nullptr;
2055 if (auto L = AliasInstMDMap.find(AliasingListMD); L != AliasInstMDMap.end())
2056 return L->second;
2057
2059 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
2060 for (const MDOperand &MDListOp : AliasingListMD->operands()) {
2061 if (MDNode *ScopeMD = dyn_cast<MDNode>(MDListOp)) {
2062 if (ScopeMD->getNumOperands() < 2)
2063 return nullptr;
2064 MDNode *DomainMD = dyn_cast<MDNode>(ScopeMD->getOperand(1));
2065 if (!DomainMD)
2066 return nullptr;
2067 auto *Domain = [&] {
2068 auto D = AliasInstMDMap.find(DomainMD);
2069 if (D != AliasInstMDMap.end())
2070 return D->second;
2071 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
2072 auto MIB =
2073 MIRBuilder.buildInstr(SPIRV::OpAliasDomainDeclINTEL).addDef(Ret);
2074 return MIB.getInstr();
2075 }();
2076 AliasInstMDMap.insert(std::make_pair(DomainMD, Domain));
2077 auto *Scope = [&] {
2078 auto S = AliasInstMDMap.find(ScopeMD);
2079 if (S != AliasInstMDMap.end())
2080 return S->second;
2081 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
2082 auto MIB = MIRBuilder.buildInstr(SPIRV::OpAliasScopeDeclINTEL)
2083 .addDef(Ret)
2084 .addUse(Domain->getOperand(0).getReg());
2085 return MIB.getInstr();
2086 }();
2087 AliasInstMDMap.insert(std::make_pair(ScopeMD, Scope));
2088 ScopeList.push_back(Scope);
2089 }
2090 }
2091
2092 const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);
2093 auto MIB =
2094 MIRBuilder.buildInstr(SPIRV::OpAliasScopeListDeclINTEL).addDef(Ret);
2095 for (auto *Scope : ScopeList)
2096 MIB.addUse(Scope->getOperand(0).getReg());
2097 auto List = MIB.getInstr();
2098 AliasInstMDMap.insert(std::make_pair(AliasingListMD, List));
2099 return List;
2100}
2101
2103 Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec,
2104 const MDNode *AliasingListMD) {
2105 MachineInstr *AliasList =
2106 getOrAddMemAliasingINTELInst(MIRBuilder, AliasingListMD);
2107 if (!AliasList)
2108 return;
2109 MIRBuilder.buildInstr(SPIRV::OpDecorate)
2110 .addUse(Reg)
2111 .addImm(Dec)
2112 .addUse(AliasList->getOperand(0).getReg());
2113}
2115 bool DeleteOld) {
2116 Old->replaceAllUsesWith(New);
2117 updateIfExistDeducedElementType(Old, New, DeleteOld);
2118 updateIfExistAssignPtrTypeInstr(Old, New, DeleteOld);
2119}
2120
2122 Value *Arg) {
2123 Value *OfType = getNormalizedPoisonValue(Ty);
2124 CallInst *AssignCI = nullptr;
2125 if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
2126 allowEmitFakeUse(Arg)) {
2127 LLVMContext &Ctx = Arg->getContext();
2130 MDString::get(Ctx, Arg->getName())};
2131 B.CreateIntrinsic(Intrinsic::spv_value_md,
2132 {MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});
2133 AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {Arg});
2134 } else {
2135 AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},
2136 OfType, Arg, {}, B);
2137 }
2138 addAssignPtrTypeInstr(Arg, AssignCI);
2139}
2140
2142 Value *Arg) {
2143 Value *OfType = PoisonValue::get(ElemTy);
2144 CallInst *AssignPtrTyCI = findAssignPtrTypeInstr(Arg);
2145 Function *CurrF =
2146 B.GetInsertBlock() ? B.GetInsertBlock()->getParent() : nullptr;
2147 if (AssignPtrTyCI == nullptr ||
2148 AssignPtrTyCI->getParent()->getParent() != CurrF) {
2149 AssignPtrTyCI = buildIntrWithMD(
2150 Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
2151 {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
2152 addDeducedElementType(AssignPtrTyCI, ElemTy);
2153 addDeducedElementType(Arg, ElemTy);
2154 addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
2155 } else {
2156 updateAssignType(AssignPtrTyCI, Arg, OfType);
2157 }
2158}
2159
2161 Value *OfType) {
2162 AssignCI->setArgOperand(1, buildMD(OfType));
2163 if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=
2164 Intrinsic::spv_assign_ptr_type)
2165 return;
2166
2167 // update association with the pointee type
2168 Type *ElemTy = OfType->getType();
2169 addDeducedElementType(AssignCI, ElemTy);
2170 addDeducedElementType(Arg, ElemTy);
2171}
2172
2173void SPIRVGlobalRegistry::addStructOffsetDecorations(
2174 Register Reg, StructType *Ty, MachineIRBuilder &MIRBuilder) {
2175 DataLayout DL;
2176 ArrayRef<TypeSize> Offsets = DL.getStructLayout(Ty)->getMemberOffsets();
2177 for (uint32_t I = 0; I < Ty->getNumElements(); ++I) {
2178 buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
2179 {static_cast<uint32_t>(Offsets[I])});
2180 }
2181}
2182
2183void SPIRVGlobalRegistry::addArrayStrideDecorations(
2184 Register Reg, Type *ElementType, MachineIRBuilder &MIRBuilder) {
2185 uint32_t SizeInBytes = DataLayout().getTypeSizeInBits(ElementType) / 8;
2186 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::ArrayStride,
2187 {SizeInBytes});
2188}
2189
2190bool SPIRVGlobalRegistry::hasBlockDecoration(SPIRVType *Type) const {
2192 for (const MachineInstr &Use :
2193 Type->getMF()->getRegInfo().use_instructions(Def)) {
2194 if (Use.getOpcode() != SPIRV::OpDecorate)
2195 continue;
2196
2197 if (Use.getOperand(1).getImm() == SPIRV::Decoration::Block)
2198 return true;
2199 }
2200 return false;
2201}
unsigned const MachineRegisterInfo * MRI
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static unsigned getNumElements(Type *Ty)
static bool storageClassRequiresExplictLayout(SPIRV::StorageClass::StorageClass SC)
static Register createTypeVReg(MachineRegisterInfo &MRI)
unsigned getAS(SPIRVType *SpvType)
static bool allowEmitFakeUse(const Value *Arg)
static unsigned typeToAddressSpace(const Type *Ty)
APInt bitcastToAPInt() const
Definition APFloat.h:1335
bool isPosZero() const
Definition APFloat.h:1442
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1541
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Class to represent array types.
uint64_t getNumElements() const
Type * getElementType() const
void setArgOperand(unsigned i, Value *v)
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:282
const APFloat & getValue() const
Definition Constants.h:326
const APFloat & getValueAPF() const
Definition Constants.h:325
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition Constants.h:491
static LLVM_ABI ConstantTargetNone * get(TargetExtType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI const APInt & getUniqueInteger() const
If C is a constant integer then return its value, otherwise C must be a vector of constant integers,...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition Constants.cpp:90
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:802
Class to represent function types.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition Value.h:576
Module * getParent()
Get the module that this global value is contained inside of...
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
MaybeAlign getAlign() const
Returns the alignment of the given variable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2794
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:318
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:90
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
Metadata node.
Definition Metadata.h:1078
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1440
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1569
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1448
Tracking metadata reference owned by Metadata.
Definition Metadata.h:900
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:608
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1526
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
LLVMContext & getContext() const
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
const DebugLoc & getDL()
Getter for DebugLoc.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
mop_range defs()
Returns all explicit operands that are register definitions.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
mop_range uses()
Returns all operands which may be register uses.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:104
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getResultType(Register VReg, MachineFunction *MF=nullptr)
void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg)
SPIRVType * getOrCreateVulkanPushConstantType(MachineIRBuilder &MIRBuilder, Type *ElemType)
SPIRVType * getOrCreatePaddingType(MachineIRBuilder &MIRBuilder)
SPIRVType * assignFloatTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
MachineInstr * getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld=true)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
SPIRVType * getOrCreateUnknownType(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode, const ArrayRef< MCOperand > Operands)
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
Register createConstInt(const ConstantInt *CI, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull)
SPIRVType * getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
void addDeducedElementType(Value *Val, Type *Ty)
SPIRVGlobalRegistry(unsigned PointerSize)
Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
Register createConstFP(const ConstantFP *CF, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull)
void updateIfExistDeducedElementType(Value *OldVal, Value *NewVal, bool DeleteOld)
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
SPIRVType * assignIntTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
unsigned getPointeeTypeOp(Register PtrReg)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType, SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr=false)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
SPIRVType * getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr=false)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg)
Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
void updateIfExistAssignPtrTypeInstr(Value *OldVal, Value *NewVal, bool DeleteOld)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getImageType(const TargetExtType *ExtensionType, const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder)
bool isResourceType(SPIRVType *Type) const
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR, bool ZeroAsNull=true)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
LLT getRegType(SPIRVType *SpvType) const
void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec, const MDNode *GVarMD)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)
void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType)
Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
CallInst * findAssignPtrTypeInstr(const Value *Val)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
const MachineInstr * findMI(SPIRV::IRHandle Handle, const MachineFunction *MF)
bool erase(const MachineInstr *MI)
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:667
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:472
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:225
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition StringRef.h:293
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:637
Class to represent struct types.
ArrayRef< Type * > elements() const
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:619
bool isPacked() const
unsigned getNumElements() const
Random access to the elements.
bool hasName() const
Return true if this is a named struct that has a non-empty name.
LLVM_ABI StringRef getName() const
Return the name for this struct type if it has an identity.
Definition Type.cpp:696
Class to represent target extensions types, which are generally unintrospectable from target-independ...
unsigned getNumIntParameters() const
Type * getTypeParameter(unsigned i) const
unsigned getNumTypeParameters() const
unsigned getIntParameter(unsigned i) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:273
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:264
Type * getArrayElementType() const
Definition Type.h:408
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:145
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:294
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:304
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:184
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:240
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:285
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:284
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:282
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:139
static LLVM_ABI TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
'undef' values are things that do not have specified contents.
Definition Constants.h:1430
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
static ConstantAsMetadata * getConstant(Value *C)
Definition Metadata.h:480
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.cpp:1106
bool hasName() const
Definition Value.h:262
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
IteratorT begin() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
IRHandle handle(const Type *Ty)
IRHandle irhandle_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy)
IRHandle irhandle_padding()
IRHandle irhandle_vkbuffer(const Type *ElementType, StorageClass::StorageClass SC, bool IsWriteable)
IRHandle irhandle_sampler()
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
IRHandle irhandle_event()
IRHandle irhandle_pipe(uint8_t AQ)
IRHandle irhandle_image(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
Definition SPIRVUtils.h:403
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:367
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:155
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
bool matchPeeledArrayPattern(const StructType *Ty, Type *&OriginalElementType, uint64_t &TotalSize)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:177
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition SPIRVUtils.h:244
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
MetadataAsValue * buildMD(Value *Arg)
Definition SPIRVUtils.h:513
bool isTypedPointerTy(const Type *T)
Definition SPIRVUtils.h:351
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * getTypedPointerWrapper(Type *ElemTy, unsigned AS)
Definition SPIRVUtils.h:398
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
void buildOpMemberDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, uint32_t Member, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
Definition SPIRVUtils.h:458
bool isSpecialOpaqueType(const Type *Ty)
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:361
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
const Type * unifyPtrType(const Type *Ty)
Definition SPIRVUtils.h:485
const MachineInstr SPIRVType
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::function< void(Register)> StructOffsetDecorator
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD, const SPIRVSubtarget &ST)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool hasBuiltinTypePrefix(StringRef Name)
bool isPointerTyOrWrapper(const Type *Ty)
Definition SPIRVUtils.h:410
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
PoisonValue * getNormalizedPoisonValue(Type *Ty)
Definition SPIRVUtils.h:509
void addStringImm(const StringRef &Str, MCInst &Inst)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:180
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:130