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