LLVM 17.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 if (Width <= 8)
85 Width = 8;
86 else if (Width <= 16)
87 Width = 16;
88 else if (Width <= 32)
89 Width = 32;
90 else if (Width <= 64)
91 Width = 64;
92
93 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
94 .addDef(createTypeVReg(MIRBuilder))
95 .addImm(Width)
96 .addImm(IsSigned ? 1 : 0);
97 return MIB;
98}
99
100SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
101 MachineIRBuilder &MIRBuilder) {
102 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
103 .addDef(createTypeVReg(MIRBuilder))
104 .addImm(Width);
105 return MIB;
106}
107
108SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
109 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
110 .addDef(createTypeVReg(MIRBuilder));
111}
112
113SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
114 SPIRVType *ElemType,
115 MachineIRBuilder &MIRBuilder) {
116 auto EleOpc = ElemType->getOpcode();
117 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
118 EleOpc == SPIRV::OpTypeBool) &&
119 "Invalid vector element type");
120
121 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
122 .addDef(createTypeVReg(MIRBuilder))
123 .addUse(getSPIRVTypeID(ElemType))
124 .addImm(NumElems);
125 return MIB;
126}
127
128std::tuple<Register, ConstantInt *, bool>
129SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
130 MachineIRBuilder *MIRBuilder,
132 const SPIRVInstrInfo *TII) {
133 const IntegerType *LLVMIntTy;
134 if (SpvType)
135 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
136 else
138 bool NewInstr = false;
139 // Find a constant in DT or build a new one.
140 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
141 Register Res = DT.find(CI, CurMF);
142 if (!Res.isValid()) {
143 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
144 LLT LLTy = LLT::scalar(32);
146 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
147 if (MIRBuilder)
148 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
149 else
151 DT.add(CI, CurMF, Res);
152 NewInstr = true;
153 }
154 return std::make_tuple(Res, CI, NewInstr);
155}
156
158 SPIRVType *SpvType,
159 const SPIRVInstrInfo &TII) {
160 assert(SpvType);
161 ConstantInt *CI;
162 Register Res;
163 bool New;
164 std::tie(Res, CI, New) =
165 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
166 // If we have found Res register which is defined by the passed G_CONSTANT
167 // machine instruction, a new constant instruction should be created.
168 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
169 return Res;
171 MachineBasicBlock &BB = *I.getParent();
172 if (Val) {
173 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
174 .addDef(Res)
175 .addUse(getSPIRVTypeID(SpvType));
176 addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
177 } else {
178 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
179 .addDef(Res)
180 .addUse(getSPIRVTypeID(SpvType));
181 }
182 const auto &ST = CurMF->getSubtarget();
183 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
184 *ST.getRegisterInfo(), *ST.getRegBankInfo());
185 return Res;
186}
187
189 MachineIRBuilder &MIRBuilder,
190 SPIRVType *SpvType,
191 bool EmitIR) {
192 auto &MF = MIRBuilder.getMF();
193 const IntegerType *LLVMIntTy;
194 if (SpvType)
195 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
196 else
197 LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
198 // Find a constant in DT or build a new one.
199 const auto ConstInt =
200 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
201 Register Res = DT.find(ConstInt, &MF);
202 if (!Res.isValid()) {
203 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
204 LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
205 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
206 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
207 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
208 SPIRV::AccessQualifier::ReadWrite, EmitIR);
209 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
210 if (EmitIR) {
211 MIRBuilder.buildConstant(Res, *ConstInt);
212 } else {
214 if (Val) {
215 assert(SpvType);
216 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
217 .addDef(Res)
218 .addUse(getSPIRVTypeID(SpvType));
219 addNumImm(APInt(BitWidth, Val), MIB);
220 } else {
221 assert(SpvType);
222 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
223 .addDef(Res)
224 .addUse(getSPIRVTypeID(SpvType));
225 }
226 const auto &Subtarget = CurMF->getSubtarget();
227 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
228 *Subtarget.getRegisterInfo(),
229 *Subtarget.getRegBankInfo());
230 }
231 }
232 return Res;
233}
234
236 MachineIRBuilder &MIRBuilder,
237 SPIRVType *SpvType) {
238 auto &MF = MIRBuilder.getMF();
239 const Type *LLVMFPTy;
240 if (SpvType) {
241 LLVMFPTy = getTypeForSPIRVType(SpvType);
242 assert(LLVMFPTy->isFloatingPointTy());
243 } else {
244 LLVMFPTy = IntegerType::getFloatTy(MF.getFunction().getContext());
245 }
246 // Find a constant in DT or build a new one.
247 const auto ConstFP = ConstantFP::get(LLVMFPTy->getContext(), Val);
248 Register Res = DT.find(ConstFP, &MF);
249 if (!Res.isValid()) {
250 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
251 Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(BitWidth));
252 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
253 assignTypeToVReg(LLVMFPTy, Res, MIRBuilder);
254 DT.add(ConstFP, &MF, Res);
255 MIRBuilder.buildFConstant(Res, *ConstFP);
256 }
257 return Res;
258}
259
260Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
261 uint64_t Val, MachineInstr &I, SPIRVType *SpvType,
262 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
263 unsigned ElemCnt) {
264 // Find a constant vector in DT or build a new one.
265 Register Res = DT.find(CA, CurMF);
266 if (!Res.isValid()) {
268 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
269 // error on validation.
270 // TODO: can moved below once sorting of types/consts/defs is implemented.
271 Register SpvScalConst;
272 if (Val)
273 SpvScalConst = getOrCreateConstInt(Val, I, SpvBaseType, TII);
274 // TODO: maybe use bitwidth of base type.
275 LLT LLTy = LLT::scalar(32);
276 Register SpvVecConst =
278 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
279 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
280 DT.add(CA, CurMF, SpvVecConst);
282 MachineBasicBlock &BB = *I.getParent();
283 if (Val) {
284 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
285 .addDef(SpvVecConst)
286 .addUse(getSPIRVTypeID(SpvType));
287 for (unsigned i = 0; i < ElemCnt; ++i)
288 MIB.addUse(SpvScalConst);
289 } else {
290 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
291 .addDef(SpvVecConst)
292 .addUse(getSPIRVTypeID(SpvType));
293 }
294 const auto &Subtarget = CurMF->getSubtarget();
295 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
296 *Subtarget.getRegisterInfo(),
297 *Subtarget.getRegBankInfo());
298 return SpvVecConst;
299 }
300 return Res;
301}
302
305 SPIRVType *SpvType,
306 const SPIRVInstrInfo &TII) {
307 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
308 assert(LLVMTy->isVectorTy());
309 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
310 Type *LLVMBaseTy = LLVMVecTy->getElementType();
311 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
312 auto ConstVec =
313 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
314 unsigned BW = getScalarOrVectorBitWidth(SpvType);
315 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstVec, BW,
316 SpvType->getOperand(2).getImm());
317}
318
321 SPIRVType *SpvType,
322 const SPIRVInstrInfo &TII) {
323 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
324 assert(LLVMTy->isArrayTy());
325 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
326 Type *LLVMBaseTy = LLVMArrTy->getElementType();
327 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
328 auto ConstArr =
329 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
330 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
331 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
332 return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstArr, BW,
333 LLVMArrTy->getNumElements());
334}
335
336Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
337 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
338 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
339 Register Res = DT.find(CA, CurMF);
340 if (!Res.isValid()) {
341 Register SpvScalConst;
342 if (Val || EmitIR) {
343 SPIRVType *SpvBaseType =
345 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
346 }
347 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
348 Register SpvVecConst =
350 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
351 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
352 DT.add(CA, CurMF, SpvVecConst);
353 if (EmitIR) {
354 MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
355 } else {
356 if (Val) {
357 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
358 .addDef(SpvVecConst)
359 .addUse(getSPIRVTypeID(SpvType));
360 for (unsigned i = 0; i < ElemCnt; ++i)
361 MIB.addUse(SpvScalConst);
362 } else {
363 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
364 .addDef(SpvVecConst)
365 .addUse(getSPIRVTypeID(SpvType));
366 }
367 }
368 return SpvVecConst;
369 }
370 return Res;
371}
372
375 MachineIRBuilder &MIRBuilder,
376 SPIRVType *SpvType, bool EmitIR) {
377 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
378 assert(LLVMTy->isVectorTy());
379 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
380 Type *LLVMBaseTy = LLVMVecTy->getElementType();
381 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
382 auto ConstVec =
383 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
384 unsigned BW = getScalarOrVectorBitWidth(SpvType);
385 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
386 ConstVec, BW,
387 SpvType->getOperand(2).getImm());
388}
389
392 MachineIRBuilder &MIRBuilder,
393 SPIRVType *SpvType, bool EmitIR) {
394 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
395 assert(LLVMTy->isArrayTy());
396 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
397 Type *LLVMBaseTy = LLVMArrTy->getElementType();
398 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
399 auto ConstArr =
400 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
401 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
402 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
403 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
404 ConstArr, BW,
405 LLVMArrTy->getNumElements());
406}
407
410 SPIRVType *SpvType) {
411 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
412 const PointerType *LLVMPtrTy = cast<PointerType>(LLVMTy);
413 // Find a constant in DT or build a new one.
414 Constant *CP = ConstantPointerNull::get(const_cast<PointerType *>(LLVMPtrTy));
415 Register Res = DT.find(CP, CurMF);
416 if (!Res.isValid()) {
417 LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
419 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
420 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
421 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
422 .addDef(Res)
423 .addUse(getSPIRVTypeID(SpvType));
424 DT.add(CP, CurMF, Res);
425 }
426 return Res;
427}
428
430 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
431 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
432 SPIRVType *SampTy;
433 if (SpvType)
434 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
435 else
436 SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t", MIRBuilder);
437
438 auto Sampler =
439 ResReg.isValid()
440 ? ResReg
441 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
442 auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
443 .addDef(Sampler)
444 .addUse(getSPIRVTypeID(SampTy))
446 .addImm(Param)
447 .addImm(FilerMode);
448 assert(Res->getOperand(0).isReg());
449 return Res->getOperand(0).getReg();
450}
451
454 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
455 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
456 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
457 bool IsInstSelector) {
458 const GlobalVariable *GVar = nullptr;
459 if (GV)
460 GVar = cast<const GlobalVariable>(GV);
461 else {
462 // If GV is not passed explicitly, use the name to find or construct
463 // the global variable.
464 Module *M = MIRBuilder.getMF().getFunction().getParent();
465 GVar = M->getGlobalVariable(Name);
466 if (GVar == nullptr) {
467 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
468 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
470 Twine(Name));
471 }
472 GV = GVar;
473 }
474 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
475 if (Reg.isValid()) {
476 if (Reg != ResVReg)
477 MIRBuilder.buildCopy(ResVReg, Reg);
478 return ResVReg;
479 }
480
481 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
482 .addDef(ResVReg)
484 .addImm(static_cast<uint32_t>(Storage));
485
486 if (Init != 0) {
487 MIB.addUse(Init->getOperand(0).getReg());
488 }
489
490 // ISel may introduce a new register on this step, so we need to add it to
491 // DT and correct its type avoiding fails on the next stage.
492 if (IsInstSelector) {
493 const auto &Subtarget = CurMF->getSubtarget();
494 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
495 *Subtarget.getRegisterInfo(),
496 *Subtarget.getRegBankInfo());
497 }
498 Reg = MIB->getOperand(0).getReg();
499 DT.add(GVar, &MIRBuilder.getMF(), Reg);
500
501 // Set to Reg the same type as ResVReg has.
502 auto MRI = MIRBuilder.getMRI();
503 assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
504 if (Reg != ResVReg) {
505 LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
506 MRI->setType(Reg, RegLLTy);
507 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
508 }
509
510 // If it's a global variable with name, output OpName for it.
511 if (GVar && GVar->hasName())
512 buildOpName(Reg, GVar->getName(), MIRBuilder);
513
514 // Output decorations for the GV.
515 // TODO: maybe move to GenerateDecorations pass.
516 if (IsConst)
517 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
518
519 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
520 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
521 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
522 }
523
524 if (HasLinkageTy)
525 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
526 {static_cast<uint32_t>(LinkageType)}, Name);
527
528 SPIRV::BuiltIn::BuiltIn BuiltInId;
529 if (getSpirvBuiltInIdByName(Name, BuiltInId))
530 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
531 {static_cast<uint32_t>(BuiltInId)});
532
533 return Reg;
534}
535
536SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
537 SPIRVType *ElemType,
538 MachineIRBuilder &MIRBuilder,
539 bool EmitIR) {
540 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
541 "Invalid array element type");
542 Register NumElementsVReg =
543 buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
544 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
545 .addDef(createTypeVReg(MIRBuilder))
546 .addUse(getSPIRVTypeID(ElemType))
547 .addUse(NumElementsVReg);
548 return MIB;
549}
550
551SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
552 MachineIRBuilder &MIRBuilder) {
553 assert(Ty->hasName());
554 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
555 Register ResVReg = createTypeVReg(MIRBuilder);
556 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
557 addStringImm(Name, MIB);
558 buildOpName(ResVReg, Name, MIRBuilder);
559 return MIB;
560}
561
562SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
563 MachineIRBuilder &MIRBuilder,
564 bool EmitIR) {
565 SmallVector<Register, 4> FieldTypes;
566 for (const auto &Elem : Ty->elements()) {
567 SPIRVType *ElemTy = findSPIRVType(Elem, MIRBuilder);
568 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
569 "Invalid struct element type");
570 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
571 }
572 Register ResVReg = createTypeVReg(MIRBuilder);
573 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
574 for (const auto &Ty : FieldTypes)
575 MIB.addUse(Ty);
576 if (Ty->hasName())
577 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
578 if (Ty->isPacked())
579 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
580 return MIB;
581}
582
583SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
584 const Type *Ty, MachineIRBuilder &MIRBuilder,
585 SPIRV::AccessQualifier::AccessQualifier AccQual) {
586 // Some OpenCL and SPIRV builtins like image2d_t are passed in as
587 // pointers, but should be treated as custom types like OpTypeImage.
588 if (auto PType = dyn_cast<PointerType>(Ty)) {
589 assert(!PType->isOpaque());
590 Ty = PType->getNonOpaquePointerElementType();
591 }
592 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
593 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
594}
595
596SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
597 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
598 MachineIRBuilder &MIRBuilder, Register Reg) {
599 if (!Reg.isValid())
600 Reg = createTypeVReg(MIRBuilder);
601 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
602 .addDef(Reg)
603 .addImm(static_cast<uint32_t>(SC))
604 .addUse(getSPIRVTypeID(ElemType));
605}
606
607SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
608 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
609 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
610 .addUse(createTypeVReg(MIRBuilder))
611 .addImm(static_cast<uint32_t>(SC));
612}
613
614SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
615 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
616 MachineIRBuilder &MIRBuilder) {
617 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
618 .addDef(createTypeVReg(MIRBuilder))
619 .addUse(getSPIRVTypeID(RetType));
620 for (const SPIRVType *ArgType : ArgTypes)
621 MIB.addUse(getSPIRVTypeID(ArgType));
622 return MIB;
623}
624
626 const Type *Ty, SPIRVType *RetType,
627 const SmallVectorImpl<SPIRVType *> &ArgTypes,
628 MachineIRBuilder &MIRBuilder) {
629 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
630 if (Reg.isValid())
631 return getSPIRVTypeForVReg(Reg);
632 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
633 return finishCreatingSPIRVType(Ty, SpirvType);
634}
635
636SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
637 const Type *Ty, MachineIRBuilder &MIRBuilder,
638 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
639 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
640 if (Reg.isValid())
641 return getSPIRVTypeForVReg(Reg);
642 if (ForwardPointerTypes.find(Ty) != ForwardPointerTypes.end())
643 return ForwardPointerTypes[Ty];
644 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
645}
646
648 assert(SpirvType && "Attempting to get type id for nullptr type.");
649 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
650 return SpirvType->uses().begin()->getReg();
651 return SpirvType->defs().begin()->getReg();
652}
653
654SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
655 const Type *Ty, MachineIRBuilder &MIRBuilder,
656 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
657 if (isSpecialOpaqueType(Ty))
658 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
659 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
660 auto t = TypeToSPIRVTypeMap.find(Ty);
661 if (t != TypeToSPIRVTypeMap.end()) {
662 auto tt = t->second.find(&MIRBuilder.getMF());
663 if (tt != t->second.end())
664 return getSPIRVTypeForVReg(tt->second);
665 }
666
667 if (auto IType = dyn_cast<IntegerType>(Ty)) {
668 const unsigned Width = IType->getBitWidth();
669 return Width == 1 ? getOpTypeBool(MIRBuilder)
670 : getOpTypeInt(Width, MIRBuilder, false);
671 }
672 if (Ty->isFloatingPointTy())
673 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
674 if (Ty->isVoidTy())
675 return getOpTypeVoid(MIRBuilder);
676 if (Ty->isVectorTy()) {
677 SPIRVType *El =
678 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
679 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
680 MIRBuilder);
681 }
682 if (Ty->isArrayTy()) {
683 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
684 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
685 }
686 if (auto SType = dyn_cast<StructType>(Ty)) {
687 if (SType->isOpaque())
688 return getOpTypeOpaque(SType, MIRBuilder);
689 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
690 }
691 if (auto FType = dyn_cast<FunctionType>(Ty)) {
692 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
694 for (const auto &t : FType->params()) {
695 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
696 }
697 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
698 }
699 if (auto PType = dyn_cast<PointerType>(Ty)) {
700 SPIRVType *SpvElementType;
701 // At the moment, all opaque pointers correspond to i8 element type.
702 // TODO: change the implementation once opaque pointers are supported
703 // in the SPIR-V specification.
704 if (PType->isOpaque())
705 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
706 else
707 SpvElementType =
708 findSPIRVType(PType->getNonOpaquePointerElementType(), MIRBuilder,
709 SPIRV::AccessQualifier::ReadWrite, EmitIR);
710 auto SC = addressSpaceToStorageClass(PType->getAddressSpace());
711 // Null pointer means we have a loop in type definitions, make and
712 // return corresponding OpTypeForwardPointer.
713 if (SpvElementType == nullptr) {
714 if (ForwardPointerTypes.find(Ty) == ForwardPointerTypes.end())
715 ForwardPointerTypes[PType] = getOpTypeForwardPointer(SC, MIRBuilder);
716 return ForwardPointerTypes[PType];
717 }
718 Register Reg(0);
719 // If we have forward pointer associated with this type, use its register
720 // operand to create OpTypePointer.
721 if (ForwardPointerTypes.find(PType) != ForwardPointerTypes.end())
722 Reg = getSPIRVTypeID(ForwardPointerTypes[PType]);
723
724 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
725 }
726 llvm_unreachable("Unable to convert LLVM type to SPIRVType");
727}
728
729SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
730 const Type *Ty, MachineIRBuilder &MIRBuilder,
731 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
732 if (TypesInProcessing.count(Ty) && !Ty->isPointerTy())
733 return nullptr;
734 TypesInProcessing.insert(Ty);
735 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
736 TypesInProcessing.erase(Ty);
737 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
738 SPIRVToLLVMType[SpirvType] = Ty;
739 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
740 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
741 // will be added later. For special types it is already added to DT.
742 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
744 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
745
746 return SpirvType;
747}
748
750 auto t = VRegToTypeMap.find(CurMF);
751 if (t != VRegToTypeMap.end()) {
752 auto tt = t->second.find(VReg);
753 if (tt != t->second.end())
754 return tt->second;
755 }
756 return nullptr;
757}
758
760 const Type *Ty, MachineIRBuilder &MIRBuilder,
761 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
762 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
763 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
764 return getSPIRVTypeForVReg(Reg);
765 TypesInProcessing.clear();
766 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
767 // Create normal pointer types for the corresponding OpTypeForwardPointers.
768 for (auto &CU : ForwardPointerTypes) {
769 const Type *Ty2 = CU.first;
770 SPIRVType *STy2 = CU.second;
771 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
772 STy2 = getSPIRVTypeForVReg(Reg);
773 else
774 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
775 if (Ty == Ty2)
776 STy = STy2;
777 }
778 ForwardPointerTypes.clear();
779 return STy;
780}
781
783 unsigned TypeOpcode) const {
785 assert(Type && "isScalarOfType VReg has no type assigned");
786 return Type->getOpcode() == TypeOpcode;
787}
788
790 unsigned TypeOpcode) const {
792 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
793 if (Type->getOpcode() == TypeOpcode)
794 return true;
795 if (Type->getOpcode() == SPIRV::OpTypeVector) {
796 Register ScalarTypeVReg = Type->getOperand(1).getReg();
797 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
798 return ScalarType->getOpcode() == TypeOpcode;
799 }
800 return false;
801}
802
803unsigned
805 assert(Type && "Invalid Type pointer");
806 if (Type->getOpcode() == SPIRV::OpTypeVector) {
807 auto EleTypeReg = Type->getOperand(1).getReg();
808 Type = getSPIRVTypeForVReg(EleTypeReg);
809 }
810 if (Type->getOpcode() == SPIRV::OpTypeInt ||
811 Type->getOpcode() == SPIRV::OpTypeFloat)
812 return Type->getOperand(1).getImm();
813 if (Type->getOpcode() == SPIRV::OpTypeBool)
814 return 1;
815 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
816}
817
819 assert(Type && "Invalid Type pointer");
820 if (Type->getOpcode() == SPIRV::OpTypeVector) {
821 auto EleTypeReg = Type->getOperand(1).getReg();
822 Type = getSPIRVTypeForVReg(EleTypeReg);
823 }
824 if (Type->getOpcode() == SPIRV::OpTypeInt)
825 return Type->getOperand(2).getImm() != 0;
826 llvm_unreachable("Attempting to get sign of non-integer type.");
827}
828
829SPIRV::StorageClass::StorageClass
832 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
833 Type->getOperand(1).isImm() && "Pointer type is expected");
834 return static_cast<SPIRV::StorageClass::StorageClass>(
835 Type->getOperand(1).getImm());
836}
837
839 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
840 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
841 SPIRV::ImageFormat::ImageFormat ImageFormat,
842 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
843 SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
844 Arrayed, Multisampled, Sampled, ImageFormat,
845 AccessQual);
846 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
847 return Res;
848 Register ResVReg = createTypeVReg(MIRBuilder);
849 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
850 return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
851 .addDef(ResVReg)
852 .addUse(getSPIRVTypeID(SampledType))
853 .addImm(Dim)
854 .addImm(Depth) // Depth (whether or not it is a Depth image).
855 .addImm(Arrayed) // Arrayed.
856 .addImm(Multisampled) // Multisampled (0 = only single-sample).
857 .addImm(Sampled) // Sampled (0 = usage known at runtime).
858 .addImm(ImageFormat)
859 .addImm(AccessQual);
860}
861
862SPIRVType *
865 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
866 return Res;
867 Register ResVReg = createTypeVReg(MIRBuilder);
868 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
869 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
870}
871
873 MachineIRBuilder &MIRBuilder,
874 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
875 SPIRV::PipeTypeDescriptor TD(AccessQual);
876 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
877 return Res;
878 Register ResVReg = createTypeVReg(MIRBuilder);
879 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
880 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
881 .addDef(ResVReg)
882 .addImm(AccessQual);
883}
884
886 MachineIRBuilder &MIRBuilder) {
888 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
889 return Res;
890 Register ResVReg = createTypeVReg(MIRBuilder);
891 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
892 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
893}
894
896 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
898 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
899 ImageType->getOperand(1).getReg())),
900 ImageType);
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::OpTypeSampledImage)
906 .addDef(ResVReg)
907 .addUse(getSPIRVTypeID(ImageType));
908}
909
911 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
912 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
913 if (ResVReg.isValid())
914 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
915 ResVReg = createTypeVReg(MIRBuilder);
916 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
917 return MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
918}
919
920const MachineInstr *
921SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
922 MachineIRBuilder &MIRBuilder) {
923 Register Reg = DT.find(TD, &MIRBuilder.getMF());
924 if (Reg.isValid())
925 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
926 return nullptr;
927}
928
929// TODO: maybe use tablegen to implement this.
930SPIRVType *
932 MachineIRBuilder &MIRBuilder) {
933 unsigned VecElts = 0;
934 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
935
936 // Parse type name in either "typeN" or "type vector[N]" format, where
937 // N is the number of elements of the vector.
938 Type *Type;
939 if (TypeStr.startswith("void")) {
940 Type = Type::getVoidTy(Ctx);
941 TypeStr = TypeStr.substr(strlen("void"));
942 } else if (TypeStr.startswith("int") || TypeStr.startswith("uint")) {
943 Type = Type::getInt32Ty(Ctx);
944 TypeStr = TypeStr.startswith("int") ? TypeStr.substr(strlen("int"))
945 : TypeStr.substr(strlen("uint"));
946 } else if (TypeStr.startswith("float")) {
947 Type = Type::getFloatTy(Ctx);
948 TypeStr = TypeStr.substr(strlen("float"));
949 } else if (TypeStr.startswith("half")) {
950 Type = Type::getHalfTy(Ctx);
951 TypeStr = TypeStr.substr(strlen("half"));
952 } else if (TypeStr.startswith("opencl.sampler_t")) {
953 Type = StructType::create(Ctx, "opencl.sampler_t");
954 } else
955 llvm_unreachable("Unable to recognize SPIRV type name.");
956 if (TypeStr.startswith(" vector[")) {
957 TypeStr = TypeStr.substr(strlen(" vector["));
958 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
959 }
960 TypeStr.getAsInteger(10, VecElts);
961 auto SpirvTy = getOrCreateSPIRVType(Type, MIRBuilder);
962 if (VecElts > 0)
963 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
964 return SpirvTy;
965}
966
967SPIRVType *
969 MachineIRBuilder &MIRBuilder) {
972 MIRBuilder);
973}
974
975SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
976 SPIRVType *SpirvType) {
977 assert(CurMF == SpirvType->getMF());
978 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
979 SPIRVToLLVMType[SpirvType] = LLVMTy;
980 DT.add(LLVMTy, CurMF, getSPIRVTypeID(SpirvType));
981 return SpirvType;
982}
983
985 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
987 Register Reg = DT.find(LLVMTy, CurMF);
988 if (Reg.isValid())
989 return getSPIRVTypeForVReg(Reg);
990 MachineBasicBlock &BB = *I.getParent();
991 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeInt))
994 .addImm(0);
995 return finishCreatingSPIRVType(LLVMTy, MIB);
996}
997
998SPIRVType *
1000 return getOrCreateSPIRVType(
1001 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1002 MIRBuilder);
1003}
1004
1005SPIRVType *
1007 const SPIRVInstrInfo &TII) {
1009 Register Reg = DT.find(LLVMTy, CurMF);
1010 if (Reg.isValid())
1011 return getSPIRVTypeForVReg(Reg);
1012 MachineBasicBlock &BB = *I.getParent();
1013 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1015 return finishCreatingSPIRVType(LLVMTy, MIB);
1016}
1017
1019 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1020 return getOrCreateSPIRVType(
1022 NumElements),
1023 MIRBuilder);
1024}
1025
1027 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1028 const SPIRVInstrInfo &TII) {
1029 Type *LLVMTy = FixedVectorType::get(
1030 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1031 Register Reg = DT.find(LLVMTy, CurMF);
1032 if (Reg.isValid())
1033 return getSPIRVTypeForVReg(Reg);
1034 MachineBasicBlock &BB = *I.getParent();
1035 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1038 .addImm(NumElements);
1039 return finishCreatingSPIRVType(LLVMTy, MIB);
1040}
1041
1043 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1044 const SPIRVInstrInfo &TII) {
1045 Type *LLVMTy = ArrayType::get(
1046 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1047 Register Reg = DT.find(LLVMTy, CurMF);
1048 if (Reg.isValid())
1049 return getSPIRVTypeForVReg(Reg);
1050 MachineBasicBlock &BB = *I.getParent();
1051 SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1052 Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1053 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1056 .addUse(Len);
1057 return finishCreatingSPIRVType(LLVMTy, MIB);
1058}
1059
1061 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1062 SPIRV::StorageClass::StorageClass SClass) {
1063 return getOrCreateSPIRVType(
1066 MIRBuilder);
1067}
1068
1071 SPIRV::StorageClass::StorageClass SC) {
1072 Type *LLVMTy =
1075 Register Reg = DT.find(LLVMTy, CurMF);
1076 if (Reg.isValid())
1077 return getSPIRVTypeForVReg(Reg);
1078 MachineBasicBlock &BB = *I.getParent();
1079 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypePointer))
1081 .addImm(static_cast<uint32_t>(SC))
1083 return finishCreatingSPIRVType(LLVMTy, MIB);
1084}
1085
1087 SPIRVType *SpvType,
1088 const SPIRVInstrInfo &TII) {
1089 assert(SpvType);
1090 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1091 assert(LLVMTy);
1092 // Find a constant in DT or build a new one.
1093 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1094 Register Res = DT.find(UV, CurMF);
1095 if (Res.isValid())
1096 return Res;
1097 LLT LLTy = LLT::scalar(32);
1099 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1100 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1101 DT.add(UV, CurMF, Res);
1102
1104 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1105 .addDef(Res)
1106 .addUse(getSPIRVTypeID(SpvType));
1107 const auto &ST = CurMF->getSubtarget();
1108 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1109 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1110 return Res;
1111}
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:75
Class to represent array types.
Definition: DerivedTypes.h:357
uint64_t getNumElements() const
Definition: DerivedTypes.h:369
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:658
Type * getElementType() const
Definition: DerivedTypes.h:370
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1242
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:1698
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1392
This is an important base class in LLVM.
Definition: Constant.h:41
Class to represent fixed width SIMD vectors.
Definition: DerivedTypes.h:525
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:704
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:319
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:331
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.
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.
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.
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:516
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:689
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:678
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:526
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:632
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:682
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isValid() const
Definition: Register.h:126
const SPIRVDuplicatesTracker< Type > * getTypes()
void add(const Type *T, const MachineFunction *MF, Register R)
Register find(const Type *T, const MachineFunction *MF)
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:468
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:558
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:295
Class to represent struct types.
Definition: DerivedTypes.h:213
ArrayRef< Type * > elements() const
Definition: DerivedTypes.h:319
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:533
bool isPacked() const
Definition: DerivedTypes.h:273
bool hasName() const
Return true if this is a named struct that has a non-empty name.
Definition: DerivedTypes.h:290
StringRef getName() const
Return the name for this struct type if it has an identity.
Definition: Type.cpp:601
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:267
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:255
bool isPointerTy() const
True if this is an instance of PointerType.
Definition: Type.h:258
Type * getArrayElementType() const
Definition: Type.h:406
Type * getNonOpaquePointerElementType() const
Only use this method in code that is not reachable with opaque pointers, or part of deprecated method...
Definition: Type.h:425
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
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 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:1375
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1731
bool hasName() const
Definition: Value.h:261
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:308
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Definition: DerivedTypes.h:627
Type * getElementType() const
Definition: DerivedTypes.h:422
#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:95
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:133
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:78
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
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:112
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
Definition: SPIRVUtils.cpp:153
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:343
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:184
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:49
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