LLVM 18.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 "SPIRVTargetMachine.h"
22#include "SPIRVUtils.h"
23
24using namespace llvm;
26 : PointerSize(PointerSize) {}
27
29 Register VReg,
31 const SPIRVInstrInfo &TII) {
33 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
34 return SpirvType;
35}
36
38 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
39 const SPIRVInstrInfo &TII) {
40 SPIRVType *SpirvType =
42 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
43 return SpirvType;
44}
45
47 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
48 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
49
50 SPIRVType *SpirvType =
51 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
52 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
53 return SpirvType;
54}
55
57 Register VReg,
58 MachineFunction &MF) {
59 VRegToTypeMap[&MF][VReg] = SpirvType;
60}
61
63 auto &MRI = MIRBuilder.getMF().getRegInfo();
64 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
65 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
66 return Res;
67}
68
70 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
71 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
72 return Res;
73}
74
75SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
76 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
77 .addDef(createTypeVReg(MIRBuilder));
78}
79
80SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width,
81 MachineIRBuilder &MIRBuilder,
82 bool IsSigned) {
83 assert(Width <= 64 && "Unsupported integer width!");
84 const SPIRVSubtarget &ST =
85 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
86 if (ST.canUseExtension(
87 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
88 MIRBuilder.buildInstr(SPIRV::OpExtension)
89 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
90 MIRBuilder.buildInstr(SPIRV::OpCapability)
91 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
92 } else if (Width <= 8)
93 Width = 8;
94 else if (Width <= 16)
95 Width = 16;
96 else if (Width <= 32)
97 Width = 32;
98 else if (Width <= 64)
99 Width = 64;
100
101 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
102 .addDef(createTypeVReg(MIRBuilder))
103 .addImm(Width)
104 .addImm(IsSigned ? 1 : 0);
105 return MIB;
106}
107
108SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
109 MachineIRBuilder &MIRBuilder) {
110 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
111 .addDef(createTypeVReg(MIRBuilder))
112 .addImm(Width);
113 return MIB;
114}
115
116SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
117 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
118 .addDef(createTypeVReg(MIRBuilder));
119}
120
121SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
122 SPIRVType *ElemType,
123 MachineIRBuilder &MIRBuilder) {
124 auto EleOpc = ElemType->getOpcode();
125 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
126 EleOpc == SPIRV::OpTypeBool) &&
127 "Invalid vector element type");
128
129 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
130 .addDef(createTypeVReg(MIRBuilder))
131 .addUse(getSPIRVTypeID(ElemType))
132 .addImm(NumElems);
133 return MIB;
134}
135
136std::tuple<Register, ConstantInt *, bool>
137SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
138 MachineIRBuilder *MIRBuilder,
140 const SPIRVInstrInfo *TII) {
141 const IntegerType *LLVMIntTy;
142 if (SpvType)
143 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
144 else
146 bool NewInstr = false;
147 // Find a constant in DT or build a new one.
148 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
149 Register Res = DT.find(CI, CurMF);
150 if (!Res.isValid()) {
151 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
152 LLT LLTy = LLT::scalar(32);
154 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
155 if (MIRBuilder)
156 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
157 else
159 DT.add(CI, CurMF, Res);
160 NewInstr = true;
161 }
162 return std::make_tuple(Res, CI, NewInstr);
163}
164
166 SPIRVType *SpvType,
167 const SPIRVInstrInfo &TII) {
168 assert(SpvType);
169 ConstantInt *CI;
170 Register Res;
171 bool New;
172 std::tie(Res, CI, New) =
173 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
174 // If we have found Res register which is defined by the passed G_CONSTANT
175 // machine instruction, a new constant instruction should be created.
176 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
177 return Res;
179 MachineBasicBlock &BB = *I.getParent();
180 if (Val) {
181 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
182 .addDef(Res)
183 .addUse(getSPIRVTypeID(SpvType));
184 addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
185 } else {
186 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
187 .addDef(Res)
188 .addUse(getSPIRVTypeID(SpvType));
189 }
190 const auto &ST = CurMF->getSubtarget();
191 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
192 *ST.getRegisterInfo(), *ST.getRegBankInfo());
193 return Res;
194}
195
197 MachineIRBuilder &MIRBuilder,
198 SPIRVType *SpvType,
199 bool EmitIR) {
200 auto &MF = MIRBuilder.getMF();
201 const IntegerType *LLVMIntTy;
202 if (SpvType)
203 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
204 else
205 LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
206 // Find a constant in DT or build a new one.
207 const auto ConstInt =
208 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
209 Register Res = DT.find(ConstInt, &MF);
210 if (!Res.isValid()) {
211 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
212 LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
213 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
214 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
215 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
216 SPIRV::AccessQualifier::ReadWrite, EmitIR);
217 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
218 if (EmitIR) {
219 MIRBuilder.buildConstant(Res, *ConstInt);
220 } else {
222 if (Val) {
223 assert(SpvType);
224 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
225 .addDef(Res)
226 .addUse(getSPIRVTypeID(SpvType));
227 addNumImm(APInt(BitWidth, Val), MIB);
228 } else {
229 assert(SpvType);
230 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
231 .addDef(Res)
232 .addUse(getSPIRVTypeID(SpvType));
233 }
234 const auto &Subtarget = CurMF->getSubtarget();
235 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
236 *Subtarget.getRegisterInfo(),
237 *Subtarget.getRegBankInfo());
238 }
239 }
240 return Res;
241}
242
244 MachineIRBuilder &MIRBuilder,
245 SPIRVType *SpvType) {
246 auto &MF = MIRBuilder.getMF();
247 const Type *LLVMFPTy;
248 if (SpvType) {
249 LLVMFPTy = getTypeForSPIRVType(SpvType);
250 assert(LLVMFPTy->isFloatingPointTy());
251 } else {
252 LLVMFPTy = IntegerType::getFloatTy(MF.getFunction().getContext());
253 }
254 // Find a constant in DT or build a new one.
255 const auto ConstFP = ConstantFP::get(LLVMFPTy->getContext(), Val);
256 Register Res = DT.find(ConstFP, &MF);
257 if (!Res.isValid()) {
258 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
259 Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(BitWidth));
260 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
261 assignTypeToVReg(LLVMFPTy, Res, MIRBuilder);
262 DT.add(ConstFP, &MF, Res);
263 MIRBuilder.buildFConstant(Res, *ConstFP);
264 }
265 return Res;
266}
267
268Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
269 uint64_t Val, MachineInstr &I, SPIRVType *SpvType,
270 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
271 unsigned ElemCnt) {
272 // Find a constant vector in DT or build a new one.
273 Register Res = DT.find(CA, CurMF);
274 if (!Res.isValid()) {
276 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
277 // error on validation.
278 // TODO: can moved below once sorting of types/consts/defs is implemented.
279 Register SpvScalConst;
280 if (Val)
281 SpvScalConst = getOrCreateConstInt(Val, I, SpvBaseType, TII);
282 // TODO: maybe use bitwidth of base type.
283 LLT LLTy = LLT::scalar(32);
284 Register SpvVecConst =
286 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
287 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
288 DT.add(CA, CurMF, SpvVecConst);
290 MachineBasicBlock &BB = *I.getParent();
291 if (Val) {
292 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
293 .addDef(SpvVecConst)
294 .addUse(getSPIRVTypeID(SpvType));
295 for (unsigned i = 0; i < ElemCnt; ++i)
296 MIB.addUse(SpvScalConst);
297 } else {
298 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
299 .addDef(SpvVecConst)
300 .addUse(getSPIRVTypeID(SpvType));
301 }
302 const auto &Subtarget = CurMF->getSubtarget();
303 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
304 *Subtarget.getRegisterInfo(),
305 *Subtarget.getRegBankInfo());
306 return SpvVecConst;
307 }
308 return Res;
309}
310
313 SPIRVType *SpvType,
314 const SPIRVInstrInfo &TII) {
315 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
316 assert(LLVMTy->isVectorTy());
317 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
318 Type *LLVMBaseTy = LLVMVecTy->getElementType();
319 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
320 auto ConstVec =
321 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
322 unsigned BW = getScalarOrVectorBitWidth(SpvType);
323 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstVec, BW,
324 SpvType->getOperand(2).getImm());
325}
326
329 SPIRVType *SpvType,
330 const SPIRVInstrInfo &TII) {
331 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
332 assert(LLVMTy->isArrayTy());
333 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
334 Type *LLVMBaseTy = LLVMArrTy->getElementType();
335 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
336 auto ConstArr =
337 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
338 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
339 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
340 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstArr, BW,
341 LLVMArrTy->getNumElements());
342}
343
344Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
345 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
346 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
347 Register Res = DT.find(CA, CurMF);
348 if (!Res.isValid()) {
349 Register SpvScalConst;
350 if (Val || EmitIR) {
351 SPIRVType *SpvBaseType =
353 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
354 }
355 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
356 Register SpvVecConst =
358 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
359 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
360 DT.add(CA, CurMF, SpvVecConst);
361 if (EmitIR) {
362 MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
363 } else {
364 if (Val) {
365 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
366 .addDef(SpvVecConst)
367 .addUse(getSPIRVTypeID(SpvType));
368 for (unsigned i = 0; i < ElemCnt; ++i)
369 MIB.addUse(SpvScalConst);
370 } else {
371 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
372 .addDef(SpvVecConst)
373 .addUse(getSPIRVTypeID(SpvType));
374 }
375 }
376 return SpvVecConst;
377 }
378 return Res;
379}
380
383 MachineIRBuilder &MIRBuilder,
384 SPIRVType *SpvType, bool EmitIR) {
385 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
386 assert(LLVMTy->isVectorTy());
387 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
388 Type *LLVMBaseTy = LLVMVecTy->getElementType();
389 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
390 auto ConstVec =
391 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
392 unsigned BW = getScalarOrVectorBitWidth(SpvType);
393 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
394 ConstVec, BW,
395 SpvType->getOperand(2).getImm());
396}
397
400 MachineIRBuilder &MIRBuilder,
401 SPIRVType *SpvType, bool EmitIR) {
402 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
403 assert(LLVMTy->isArrayTy());
404 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
405 Type *LLVMBaseTy = LLVMArrTy->getElementType();
406 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
407 auto ConstArr =
408 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
409 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
410 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
411 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
412 ConstArr, BW,
413 LLVMArrTy->getNumElements());
414}
415
418 SPIRVType *SpvType) {
419 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
420 const PointerType *LLVMPtrTy = cast<PointerType>(LLVMTy);
421 // Find a constant in DT or build a new one.
422 Constant *CP = ConstantPointerNull::get(const_cast<PointerType *>(LLVMPtrTy));
423 Register Res = DT.find(CP, CurMF);
424 if (!Res.isValid()) {
425 LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
427 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
428 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
429 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
430 .addDef(Res)
431 .addUse(getSPIRVTypeID(SpvType));
432 DT.add(CP, CurMF, Res);
433 }
434 return Res;
435}
436
438 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
439 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
440 SPIRVType *SampTy;
441 if (SpvType)
442 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
443 else
444 SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t", MIRBuilder);
445
446 auto Sampler =
447 ResReg.isValid()
448 ? ResReg
449 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
450 auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
451 .addDef(Sampler)
452 .addUse(getSPIRVTypeID(SampTy))
454 .addImm(Param)
455 .addImm(FilerMode);
456 assert(Res->getOperand(0).isReg());
457 return Res->getOperand(0).getReg();
458}
459
462 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
463 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
464 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
465 bool IsInstSelector) {
466 const GlobalVariable *GVar = nullptr;
467 if (GV)
468 GVar = cast<const GlobalVariable>(GV);
469 else {
470 // If GV is not passed explicitly, use the name to find or construct
471 // the global variable.
472 Module *M = MIRBuilder.getMF().getFunction().getParent();
473 GVar = M->getGlobalVariable(Name);
474 if (GVar == nullptr) {
475 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
476 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
478 Twine(Name));
479 }
480 GV = GVar;
481 }
482 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
483 if (Reg.isValid()) {
484 if (Reg != ResVReg)
485 MIRBuilder.buildCopy(ResVReg, Reg);
486 return ResVReg;
487 }
488
489 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
490 .addDef(ResVReg)
492 .addImm(static_cast<uint32_t>(Storage));
493
494 if (Init != 0) {
495 MIB.addUse(Init->getOperand(0).getReg());
496 }
497
498 // ISel may introduce a new register on this step, so we need to add it to
499 // DT and correct its type avoiding fails on the next stage.
500 if (IsInstSelector) {
501 const auto &Subtarget = CurMF->getSubtarget();
502 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
503 *Subtarget.getRegisterInfo(),
504 *Subtarget.getRegBankInfo());
505 }
506 Reg = MIB->getOperand(0).getReg();
507 DT.add(GVar, &MIRBuilder.getMF(), Reg);
508
509 // Set to Reg the same type as ResVReg has.
510 auto MRI = MIRBuilder.getMRI();
511 assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
512 if (Reg != ResVReg) {
513 LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
514 MRI->setType(Reg, RegLLTy);
515 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
516 }
517
518 // If it's a global variable with name, output OpName for it.
519 if (GVar && GVar->hasName())
520 buildOpName(Reg, GVar->getName(), MIRBuilder);
521
522 // Output decorations for the GV.
523 // TODO: maybe move to GenerateDecorations pass.
524 if (IsConst)
525 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
526
527 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
528 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
529 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
530 }
531
532 if (HasLinkageTy)
533 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
534 {static_cast<uint32_t>(LinkageType)}, Name);
535
536 SPIRV::BuiltIn::BuiltIn BuiltInId;
537 if (getSpirvBuiltInIdByName(Name, BuiltInId))
538 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
539 {static_cast<uint32_t>(BuiltInId)});
540
541 return Reg;
542}
543
544SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
545 SPIRVType *ElemType,
546 MachineIRBuilder &MIRBuilder,
547 bool EmitIR) {
548 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
549 "Invalid array element type");
550 Register NumElementsVReg =
551 buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
552 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
553 .addDef(createTypeVReg(MIRBuilder))
554 .addUse(getSPIRVTypeID(ElemType))
555 .addUse(NumElementsVReg);
556 return MIB;
557}
558
559SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
560 MachineIRBuilder &MIRBuilder) {
561 assert(Ty->hasName());
562 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
563 Register ResVReg = createTypeVReg(MIRBuilder);
564 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
565 addStringImm(Name, MIB);
566 buildOpName(ResVReg, Name, MIRBuilder);
567 return MIB;
568}
569
570SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
571 MachineIRBuilder &MIRBuilder,
572 bool EmitIR) {
573 SmallVector<Register, 4> FieldTypes;
574 for (const auto &Elem : Ty->elements()) {
575 SPIRVType *ElemTy = findSPIRVType(Elem, MIRBuilder);
576 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
577 "Invalid struct element type");
578 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
579 }
580 Register ResVReg = createTypeVReg(MIRBuilder);
581 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
582 for (const auto &Ty : FieldTypes)
583 MIB.addUse(Ty);
584 if (Ty->hasName())
585 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
586 if (Ty->isPacked())
587 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
588 return MIB;
589}
590
591SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
592 const Type *Ty, MachineIRBuilder &MIRBuilder,
593 SPIRV::AccessQualifier::AccessQualifier AccQual) {
594 // Some OpenCL and SPIRV builtins like image2d_t are passed in as
595 // pointers, but should be treated as custom types like OpTypeImage.
596 if (auto PType = dyn_cast<PointerType>(Ty)) {
597 assert(!PType->isOpaque());
598 Ty = PType->getNonOpaquePointerElementType();
599 }
600 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
601 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
602}
603
604SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
605 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
606 MachineIRBuilder &MIRBuilder, Register Reg) {
607 if (!Reg.isValid())
608 Reg = createTypeVReg(MIRBuilder);
609 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
610 .addDef(Reg)
611 .addImm(static_cast<uint32_t>(SC))
612 .addUse(getSPIRVTypeID(ElemType));
613}
614
615SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
616 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
617 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
618 .addUse(createTypeVReg(MIRBuilder))
619 .addImm(static_cast<uint32_t>(SC));
620}
621
622SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
623 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
624 MachineIRBuilder &MIRBuilder) {
625 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
626 .addDef(createTypeVReg(MIRBuilder))
627 .addUse(getSPIRVTypeID(RetType));
628 for (const SPIRVType *ArgType : ArgTypes)
629 MIB.addUse(getSPIRVTypeID(ArgType));
630 return MIB;
631}
632
634 const Type *Ty, SPIRVType *RetType,
635 const SmallVectorImpl<SPIRVType *> &ArgTypes,
636 MachineIRBuilder &MIRBuilder) {
637 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
638 if (Reg.isValid())
639 return getSPIRVTypeForVReg(Reg);
640 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
641 DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
642 return finishCreatingSPIRVType(Ty, SpirvType);
643}
644
645SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
646 const Type *Ty, MachineIRBuilder &MIRBuilder,
647 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
648 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
649 if (Reg.isValid())
650 return getSPIRVTypeForVReg(Reg);
651 if (ForwardPointerTypes.find(Ty) != ForwardPointerTypes.end())
652 return ForwardPointerTypes[Ty];
653 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
654}
655
657 assert(SpirvType && "Attempting to get type id for nullptr type.");
658 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
659 return SpirvType->uses().begin()->getReg();
660 return SpirvType->defs().begin()->getReg();
661}
662
663SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
664 const Type *Ty, MachineIRBuilder &MIRBuilder,
665 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
666 if (isSpecialOpaqueType(Ty))
667 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
668 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
669 auto t = TypeToSPIRVTypeMap.find(Ty);
670 if (t != TypeToSPIRVTypeMap.end()) {
671 auto tt = t->second.find(&MIRBuilder.getMF());
672 if (tt != t->second.end())
673 return getSPIRVTypeForVReg(tt->second);
674 }
675
676 if (auto IType = dyn_cast<IntegerType>(Ty)) {
677 const unsigned Width = IType->getBitWidth();
678 return Width == 1 ? getOpTypeBool(MIRBuilder)
679 : getOpTypeInt(Width, MIRBuilder, false);
680 }
681 if (Ty->isFloatingPointTy())
682 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
683 if (Ty->isVoidTy())
684 return getOpTypeVoid(MIRBuilder);
685 if (Ty->isVectorTy()) {
686 SPIRVType *El =
687 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
688 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
689 MIRBuilder);
690 }
691 if (Ty->isArrayTy()) {
692 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
693 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
694 }
695 if (auto SType = dyn_cast<StructType>(Ty)) {
696 if (SType->isOpaque())
697 return getOpTypeOpaque(SType, MIRBuilder);
698 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
699 }
700 if (auto FType = dyn_cast<FunctionType>(Ty)) {
701 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
703 for (const auto &t : FType->params()) {
704 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
705 }
706 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
707 }
708 if (auto PType = dyn_cast<PointerType>(Ty)) {
709 SPIRVType *SpvElementType;
710 // At the moment, all opaque pointers correspond to i8 element type.
711 // TODO: change the implementation once opaque pointers are supported
712 // in the SPIR-V specification.
713 if (PType->isOpaque())
714 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
715 else
716 SpvElementType =
717 findSPIRVType(PType->getNonOpaquePointerElementType(), MIRBuilder,
718 SPIRV::AccessQualifier::ReadWrite, EmitIR);
719 auto SC = addressSpaceToStorageClass(PType->getAddressSpace());
720 // Null pointer means we have a loop in type definitions, make and
721 // return corresponding OpTypeForwardPointer.
722 if (SpvElementType == nullptr) {
723 if (ForwardPointerTypes.find(Ty) == ForwardPointerTypes.end())
724 ForwardPointerTypes[PType] = getOpTypeForwardPointer(SC, MIRBuilder);
725 return ForwardPointerTypes[PType];
726 }
727 Register Reg(0);
728 // If we have forward pointer associated with this type, use its register
729 // operand to create OpTypePointer.
730 if (ForwardPointerTypes.find(PType) != ForwardPointerTypes.end())
731 Reg = getSPIRVTypeID(ForwardPointerTypes[PType]);
732
733 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
734 }
735 llvm_unreachable("Unable to convert LLVM type to SPIRVType");
736}
737
738SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
739 const Type *Ty, MachineIRBuilder &MIRBuilder,
740 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
741 if (TypesInProcessing.count(Ty) && !Ty->isPointerTy())
742 return nullptr;
743 TypesInProcessing.insert(Ty);
744 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
745 TypesInProcessing.erase(Ty);
746 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
747 SPIRVToLLVMType[SpirvType] = Ty;
748 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
749 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
750 // will be added later. For special types it is already added to DT.
751 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
752 !isSpecialOpaqueType(Ty)) {
753 if (!Ty->isPointerTy())
754 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
755 else if (Ty->isOpaquePointerTy())
756 DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
757 Ty->getPointerAddressSpace(), &MIRBuilder.getMF(),
758 getSPIRVTypeID(SpirvType));
759 else
761 &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
762 }
763
764 return SpirvType;
765}
766
768 auto t = VRegToTypeMap.find(CurMF);
769 if (t != VRegToTypeMap.end()) {
770 auto tt = t->second.find(VReg);
771 if (tt != t->second.end())
772 return tt->second;
773 }
774 return nullptr;
775}
776
778 const Type *Ty, MachineIRBuilder &MIRBuilder,
779 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
780 Register Reg;
781 if (!Ty->isPointerTy())
782 Reg = DT.find(Ty, &MIRBuilder.getMF());
783 else
784 Reg =
785 DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
786 Ty->getPointerAddressSpace(), &MIRBuilder.getMF());
787
788 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
789 return getSPIRVTypeForVReg(Reg);
790 TypesInProcessing.clear();
791 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
792 // Create normal pointer types for the corresponding OpTypeForwardPointers.
793 for (auto &CU : ForwardPointerTypes) {
794 const Type *Ty2 = CU.first;
795 SPIRVType *STy2 = CU.second;
796 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
797 STy2 = getSPIRVTypeForVReg(Reg);
798 else
799 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
800 if (Ty == Ty2)
801 STy = STy2;
802 }
803 ForwardPointerTypes.clear();
804 return STy;
805}
806
808 unsigned TypeOpcode) const {
810 assert(Type && "isScalarOfType VReg has no type assigned");
811 return Type->getOpcode() == TypeOpcode;
812}
813
815 unsigned TypeOpcode) const {
817 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
818 if (Type->getOpcode() == TypeOpcode)
819 return true;
820 if (Type->getOpcode() == SPIRV::OpTypeVector) {
821 Register ScalarTypeVReg = Type->getOperand(1).getReg();
822 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
823 return ScalarType->getOpcode() == TypeOpcode;
824 }
825 return false;
826}
827
828unsigned
830 assert(Type && "Invalid Type pointer");
831 if (Type->getOpcode() == SPIRV::OpTypeVector) {
832 auto EleTypeReg = Type->getOperand(1).getReg();
833 Type = getSPIRVTypeForVReg(EleTypeReg);
834 }
835 if (Type->getOpcode() == SPIRV::OpTypeInt ||
836 Type->getOpcode() == SPIRV::OpTypeFloat)
837 return Type->getOperand(1).getImm();
838 if (Type->getOpcode() == SPIRV::OpTypeBool)
839 return 1;
840 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
841}
842
844 assert(Type && "Invalid Type pointer");
845 if (Type->getOpcode() == SPIRV::OpTypeVector) {
846 auto EleTypeReg = Type->getOperand(1).getReg();
847 Type = getSPIRVTypeForVReg(EleTypeReg);
848 }
849 if (Type->getOpcode() == SPIRV::OpTypeInt)
850 return Type->getOperand(2).getImm() != 0;
851 llvm_unreachable("Attempting to get sign of non-integer type.");
852}
853
854SPIRV::StorageClass::StorageClass
857 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
858 Type->getOperand(1).isImm() && "Pointer type is expected");
859 return static_cast<SPIRV::StorageClass::StorageClass>(
860 Type->getOperand(1).getImm());
861}
862
864 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
865 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
866 SPIRV::ImageFormat::ImageFormat ImageFormat,
867 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
868 SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
869 Arrayed, Multisampled, Sampled, ImageFormat,
870 AccessQual);
871 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
872 return Res;
873 Register ResVReg = createTypeVReg(MIRBuilder);
874 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
875 return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
876 .addDef(ResVReg)
877 .addUse(getSPIRVTypeID(SampledType))
878 .addImm(Dim)
879 .addImm(Depth) // Depth (whether or not it is a Depth image).
880 .addImm(Arrayed) // Arrayed.
881 .addImm(Multisampled) // Multisampled (0 = only single-sample).
882 .addImm(Sampled) // Sampled (0 = usage known at runtime).
883 .addImm(ImageFormat)
884 .addImm(AccessQual);
885}
886
887SPIRVType *
890 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
891 return Res;
892 Register ResVReg = createTypeVReg(MIRBuilder);
893 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
894 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
895}
896
898 MachineIRBuilder &MIRBuilder,
899 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
900 SPIRV::PipeTypeDescriptor TD(AccessQual);
901 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
902 return Res;
903 Register ResVReg = createTypeVReg(MIRBuilder);
904 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
905 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
906 .addDef(ResVReg)
907 .addImm(AccessQual);
908}
909
911 MachineIRBuilder &MIRBuilder) {
913 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
914 return Res;
915 Register ResVReg = createTypeVReg(MIRBuilder);
916 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
917 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
918}
919
921 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
923 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
924 ImageType->getOperand(1).getReg())),
925 ImageType);
926 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
927 return Res;
928 Register ResVReg = createTypeVReg(MIRBuilder);
929 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
930 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
931 .addDef(ResVReg)
932 .addUse(getSPIRVTypeID(ImageType));
933}
934
936 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
937 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
938 if (ResVReg.isValid())
939 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
940 ResVReg = createTypeVReg(MIRBuilder);
941 SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
942 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
943 return SpirvTy;
944}
945
946const MachineInstr *
947SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
948 MachineIRBuilder &MIRBuilder) {
949 Register Reg = DT.find(TD, &MIRBuilder.getMF());
950 if (Reg.isValid())
951 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
952 return nullptr;
953}
954
955// TODO: maybe use tablegen to implement this.
956SPIRVType *
958 MachineIRBuilder &MIRBuilder) {
959 unsigned VecElts = 0;
960 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
961
962 // Parse type name in either "typeN" or "type vector[N]" format, where
963 // N is the number of elements of the vector.
964 Type *Type;
965 if (TypeStr.startswith("void")) {
966 Type = Type::getVoidTy(Ctx);
967 TypeStr = TypeStr.substr(strlen("void"));
968 } else if (TypeStr.startswith("int") || TypeStr.startswith("uint")) {
969 Type = Type::getInt32Ty(Ctx);
970 TypeStr = TypeStr.startswith("int") ? TypeStr.substr(strlen("int"))
971 : TypeStr.substr(strlen("uint"));
972 } else if (TypeStr.startswith("float")) {
973 Type = Type::getFloatTy(Ctx);
974 TypeStr = TypeStr.substr(strlen("float"));
975 } else if (TypeStr.startswith("half")) {
976 Type = Type::getHalfTy(Ctx);
977 TypeStr = TypeStr.substr(strlen("half"));
978 } else if (TypeStr.startswith("opencl.sampler_t")) {
979 Type = StructType::create(Ctx, "opencl.sampler_t");
980 } else
981 llvm_unreachable("Unable to recognize SPIRV type name.");
982 if (TypeStr.startswith(" vector[")) {
983 TypeStr = TypeStr.substr(strlen(" vector["));
984 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
985 }
986 TypeStr.getAsInteger(10, VecElts);
987 auto SpirvTy = getOrCreateSPIRVType(Type, MIRBuilder);
988 if (VecElts > 0)
989 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
990 return SpirvTy;
991}
992
993SPIRVType *
995 MachineIRBuilder &MIRBuilder) {
998 MIRBuilder);
999}
1000
1001SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1002 SPIRVType *SpirvType) {
1003 assert(CurMF == SpirvType->getMF());
1004 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1005 SPIRVToLLVMType[SpirvType] = LLVMTy;
1006 return SpirvType;
1007}
1008
1010 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1012 Register Reg = DT.find(LLVMTy, CurMF);
1013 if (Reg.isValid())
1014 return getSPIRVTypeForVReg(Reg);
1015 MachineBasicBlock &BB = *I.getParent();
1016 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeInt))
1019 .addImm(0);
1020 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1021 return finishCreatingSPIRVType(LLVMTy, MIB);
1022}
1023
1024SPIRVType *
1026 return getOrCreateSPIRVType(
1027 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1028 MIRBuilder);
1029}
1030
1031SPIRVType *
1033 const SPIRVInstrInfo &TII) {
1035 Register Reg = DT.find(LLVMTy, CurMF);
1036 if (Reg.isValid())
1037 return getSPIRVTypeForVReg(Reg);
1038 MachineBasicBlock &BB = *I.getParent();
1039 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1041 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1042 return finishCreatingSPIRVType(LLVMTy, MIB);
1043}
1044
1046 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1047 return getOrCreateSPIRVType(
1049 NumElements),
1050 MIRBuilder);
1051}
1052
1054 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1055 const SPIRVInstrInfo &TII) {
1056 Type *LLVMTy = FixedVectorType::get(
1057 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1058 Register Reg = DT.find(LLVMTy, CurMF);
1059 if (Reg.isValid())
1060 return getSPIRVTypeForVReg(Reg);
1061 MachineBasicBlock &BB = *I.getParent();
1062 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1065 .addImm(NumElements);
1066 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1067 return finishCreatingSPIRVType(LLVMTy, MIB);
1068}
1069
1071 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1072 const SPIRVInstrInfo &TII) {
1073 Type *LLVMTy = ArrayType::get(
1074 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1075 Register Reg = DT.find(LLVMTy, CurMF);
1076 if (Reg.isValid())
1077 return getSPIRVTypeForVReg(Reg);
1078 MachineBasicBlock &BB = *I.getParent();
1079 SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1080 Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1081 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1084 .addUse(Len);
1085 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1086 return finishCreatingSPIRVType(LLVMTy, MIB);
1087}
1088
1090 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1091 SPIRV::StorageClass::StorageClass SC) {
1092 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1094 Type *LLVMTy =
1095 PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
1096 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1097 if (Reg.isValid())
1098 return getSPIRVTypeForVReg(Reg);
1099 auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1100 MIRBuilder.getDebugLoc(),
1101 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1103 .addImm(static_cast<uint32_t>(SC))
1105 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1106 return finishCreatingSPIRVType(LLVMTy, MIB);
1107}
1108
1111 SPIRV::StorageClass::StorageClass SC) {
1112 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1114 Type *LLVMTy =
1115 PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
1116 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1117 if (Reg.isValid())
1118 return getSPIRVTypeForVReg(Reg);
1119 MachineBasicBlock &BB = *I.getParent();
1120 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypePointer))
1122 .addImm(static_cast<uint32_t>(SC))
1124 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1125 return finishCreatingSPIRVType(LLVMTy, MIB);
1126}
1127
1129 SPIRVType *SpvType,
1130 const SPIRVInstrInfo &TII) {
1131 assert(SpvType);
1132 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1133 assert(LLVMTy);
1134 // Find a constant in DT or build a new one.
1135 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1136 Register Res = DT.find(UV, CurMF);
1137 if (Res.isValid())
1138 return Res;
1139 LLT LLTy = LLT::scalar(32);
1141 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1142 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1143 DT.add(UV, CurMF, Res);
1144
1146 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1147 .addDef(Res)
1148 .addUse(getSPIRVTypeID(SpvType));
1149 const auto &ST = CurMF->getSubtarget();
1150 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1151 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1152 return Res;
1153}
unsigned const MachineRegisterInfo * MRI
return RetTy
std::string Name
const HexagonInstrInfo * TII
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Register createTypeVReg(MachineIRBuilder &MIRBuilder)
Class for arbitrary precision integers.
Definition: APInt.h:76
Class to represent array types.
Definition: DerivedTypes.h:368
uint64_t getNumElements() const
Definition: DerivedTypes.h:380
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:648
Type * getElementType() const
Definition: DerivedTypes.h:381
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1235
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:927
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1691
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1385
This is an important base class in LLVM.
Definition: Constant.h:41
Class to represent fixed width SIMD vectors.
Definition: DerivedTypes.h:536
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:693
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:320
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:79
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:652
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:48
Class to represent integer types.
Definition: DerivedTypes.h:40
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:279
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
Definition: LowLevelType.h:49
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
Definition: LowLevelType.h:92
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:543
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:707
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:696
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:553
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Class to represent pointers.
Definition: DerivedTypes.h:643
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:690
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isValid() const
Definition: Register.h:116
void add(const Type *Ty, const MachineFunction *MF, Register R)
Register find(const Type *Ty, const MachineFunction *MF)
const SPIRVDuplicatesTracker< Type > * getTypes()
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
Register getOrCreateConsIntVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder)
SPIRVType * assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
SPIRVType * getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled, SPIRV::ImageFormat::ImageFormat ImageFormat, SPIRV::AccessQualifier::AccessQualifier AccQual)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg) const
SPIRVGlobalRegistry(unsigned PointerSize)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, bool HasLinkageTy, SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
SPIRVType * assignIntTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register getOrCreateConsIntArray(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVArrayType(SPIRVType *BaseType, unsigned NumElements, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr, bool EmitIR=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:474
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:575
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:301
Class to represent struct types.
Definition: DerivedTypes.h:213
ArrayRef< Type * > elements() const
Definition: DerivedTypes.h:330
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:514
bool isPacked() const
Definition: DerivedTypes.h:275
bool hasName() const
Return true if this is a named struct that has a non-empty name.
Definition: DerivedTypes.h:301
StringRef getName() const
Return the name for this struct type if it has an identity.
Definition: Type.cpp:591
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Type * getHalfTy(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:265
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:252
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:255
Type * getArrayElementType() const
Definition: Type.h:404
Type * getNonOpaquePointerElementType() const
Only use this method in code that is not reachable with opaque pointers, or part of deprecated method...
Definition: Type.h:415
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
uint64_t getArrayNumElements() const
static Type * getVoidTy(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:129
static IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:185
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isOpaquePointerTy() const
True if this is an instance of an opaque PointerType.
Definition: Type.h:259
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:140
'undef' values are things that do not have specified contents.
Definition: Constants.h:1368
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1724
bool hasName() const
Definition: Value.h:261
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Definition: DerivedTypes.h:638
Type * getElementType() const
Definition: DerivedTypes.h:433
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
Definition: SPIRVUtils.cpp:96
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:134
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:79
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition: Utils.cpp:152
AddressSpace
Definition: NVPTXBaseInfo.h:21
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:113
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
Definition: SPIRVUtils.cpp:154
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:341
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:184
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:50
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition: Alignment.h:141