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