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