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