LLVM 20.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#include "llvm/ADT/APInt.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/Type.h"
27#include <cassert>
28
29using namespace llvm;
31 : PointerSize(PointerSize), Bound(0) {}
32
34 Register VReg,
36 const SPIRVInstrInfo &TII) {
38 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
39 return SpirvType;
40}
41
45 const SPIRVInstrInfo &TII) {
47 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
48 return SpirvType;
49}
50
52 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
53 const SPIRVInstrInfo &TII) {
54 SPIRVType *SpirvType =
56 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
57 return SpirvType;
58}
59
61 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
62 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
63 SPIRVType *SpirvType =
64 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
65 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
66 return SpirvType;
67}
68
70 Register VReg,
71 MachineFunction &MF) {
72 VRegToTypeMap[&MF][VReg] = SpirvType;
73}
74
76 auto &MRI = MIRBuilder.getMF().getRegInfo();
77 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
78 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
79 return Res;
80}
81
83 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
84 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
85 return Res;
86}
87
88SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
89 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
90 .addDef(createTypeVReg(MIRBuilder));
91}
92
93unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
94 if (Width > 64)
95 report_fatal_error("Unsupported integer width!");
96 const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
97 if (ST.canUseExtension(
98 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers))
99 return Width;
100 if (Width <= 8)
101 Width = 8;
102 else if (Width <= 16)
103 Width = 16;
104 else if (Width <= 32)
105 Width = 32;
106 else
107 Width = 64;
108 return Width;
109}
110
111SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
112 MachineIRBuilder &MIRBuilder,
113 bool IsSigned) {
114 Width = adjustOpTypeIntWidth(Width);
115 const SPIRVSubtarget &ST =
116 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
117 if (ST.canUseExtension(
118 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
119 MIRBuilder.buildInstr(SPIRV::OpExtension)
120 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
121 MIRBuilder.buildInstr(SPIRV::OpCapability)
122 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
123 }
124 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
125 .addDef(createTypeVReg(MIRBuilder))
126 .addImm(Width)
127 .addImm(IsSigned ? 1 : 0);
128 return MIB;
129}
130
131SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
132 MachineIRBuilder &MIRBuilder) {
133 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
134 .addDef(createTypeVReg(MIRBuilder))
135 .addImm(Width);
136 return MIB;
137}
138
139SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
140 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
141 .addDef(createTypeVReg(MIRBuilder));
142}
143
144SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
145 SPIRVType *ElemType,
146 MachineIRBuilder &MIRBuilder) {
147 auto EleOpc = ElemType->getOpcode();
148 (void)EleOpc;
149 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
150 EleOpc == SPIRV::OpTypeBool) &&
151 "Invalid vector element type");
152
153 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
154 .addDef(createTypeVReg(MIRBuilder))
155 .addUse(getSPIRVTypeID(ElemType))
156 .addImm(NumElems);
157 return MIB;
158}
159
160std::tuple<Register, ConstantInt *, bool>
161SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
162 MachineIRBuilder *MIRBuilder,
164 const SPIRVInstrInfo *TII) {
165 const IntegerType *LLVMIntTy;
166 if (SpvType)
167 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
168 else
170 bool NewInstr = false;
171 // Find a constant in DT or build a new one.
172 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
173 Register Res = DT.find(CI, CurMF);
174 if (!Res.isValid()) {
175 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
176 // TODO: handle cases where the type is not 32bit wide
177 // TODO: https://github.com/llvm/llvm-project/issues/88129
178 LLT LLTy = LLT::scalar(32);
180 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
181 if (MIRBuilder)
182 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
183 else
185 DT.add(CI, CurMF, Res);
186 NewInstr = true;
187 }
188 return std::make_tuple(Res, CI, NewInstr);
189}
190
191std::tuple<Register, ConstantFP *, bool, unsigned>
192SPIRVGlobalRegistry::getOrCreateConstFloatReg(APFloat Val, SPIRVType *SpvType,
193 MachineIRBuilder *MIRBuilder,
195 const SPIRVInstrInfo *TII) {
196 const Type *LLVMFloatTy;
198 unsigned BitWidth = 32;
199 if (SpvType)
200 LLVMFloatTy = getTypeForSPIRVType(SpvType);
201 else {
202 LLVMFloatTy = Type::getFloatTy(Ctx);
203 if (MIRBuilder)
204 SpvType = getOrCreateSPIRVType(LLVMFloatTy, *MIRBuilder);
205 }
206 bool NewInstr = false;
207 // Find a constant in DT or build a new one.
208 auto *const CI = ConstantFP::get(Ctx, Val);
209 Register Res = DT.find(CI, CurMF);
210 if (!Res.isValid()) {
211 if (SpvType)
213 // TODO: handle cases where the type is not 32bit wide
214 // TODO: https://github.com/llvm/llvm-project/issues/88129
215 LLT LLTy = LLT::scalar(32);
217 CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
218 if (MIRBuilder)
219 assignTypeToVReg(LLVMFloatTy, Res, *MIRBuilder);
220 else
222 DT.add(CI, CurMF, Res);
223 NewInstr = true;
224 }
225 return std::make_tuple(Res, CI, NewInstr, BitWidth);
226}
227
229 SPIRVType *SpvType,
230 const SPIRVInstrInfo &TII,
231 bool ZeroAsNull) {
232 assert(SpvType);
233 ConstantFP *CI;
234 Register Res;
235 bool New;
236 unsigned BitWidth;
237 std::tie(Res, CI, New, BitWidth) =
238 getOrCreateConstFloatReg(Val, SpvType, nullptr, &I, &TII);
239 // If we have found Res register which is defined by the passed G_CONSTANT
240 // machine instruction, a new constant instruction should be created.
241 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
242 return Res;
244 MachineBasicBlock &BB = *I.getParent();
245 // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
246 if (Val.isPosZero() && ZeroAsNull) {
247 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
248 .addDef(Res)
249 .addUse(getSPIRVTypeID(SpvType));
250 } else {
251 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantF))
252 .addDef(Res)
253 .addUse(getSPIRVTypeID(SpvType));
254 addNumImm(
256 MIB);
257 }
258 const auto &ST = CurMF->getSubtarget();
259 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
260 *ST.getRegisterInfo(), *ST.getRegBankInfo());
261 return Res;
262}
263
265 SPIRVType *SpvType,
266 const SPIRVInstrInfo &TII,
267 bool ZeroAsNull) {
268 assert(SpvType);
269 ConstantInt *CI;
270 Register Res;
271 bool New;
272 std::tie(Res, CI, New) =
273 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
274 // If we have found Res register which is defined by the passed G_CONSTANT
275 // machine instruction, a new constant instruction should be created.
276 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
277 return Res;
279 MachineBasicBlock &BB = *I.getParent();
280 if (Val || !ZeroAsNull) {
281 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
282 .addDef(Res)
283 .addUse(getSPIRVTypeID(SpvType));
284 addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
285 } else {
286 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
287 .addDef(Res)
288 .addUse(getSPIRVTypeID(SpvType));
289 }
290 const auto &ST = CurMF->getSubtarget();
291 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
292 *ST.getRegisterInfo(), *ST.getRegBankInfo());
293 return Res;
294}
295
297 MachineIRBuilder &MIRBuilder,
298 SPIRVType *SpvType,
299 bool EmitIR) {
300 auto &MF = MIRBuilder.getMF();
301 const IntegerType *LLVMIntTy;
302 if (SpvType)
303 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
304 else
305 LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
306 // Find a constant in DT or build a new one.
307 const auto ConstInt =
308 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
309 Register Res = DT.find(ConstInt, &MF);
310 if (!Res.isValid()) {
311 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
312 LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
313 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
314 MF.getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
315 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
316 SPIRV::AccessQualifier::ReadWrite, EmitIR);
317 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
318 if (EmitIR) {
319 MIRBuilder.buildConstant(Res, *ConstInt);
320 } else {
321 if (!SpvType)
322 SpvType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
324 if (Val) {
325 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
326 .addDef(Res)
327 .addUse(getSPIRVTypeID(SpvType));
328 addNumImm(APInt(BitWidth, Val), MIB);
329 } else {
330 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
331 .addDef(Res)
332 .addUse(getSPIRVTypeID(SpvType));
333 }
334 const auto &Subtarget = CurMF->getSubtarget();
335 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
336 *Subtarget.getRegisterInfo(),
337 *Subtarget.getRegBankInfo());
338 }
339 }
340 return Res;
341}
342
344 MachineIRBuilder &MIRBuilder,
345 SPIRVType *SpvType) {
346 auto &MF = MIRBuilder.getMF();
347 auto &Ctx = MF.getFunction().getContext();
348 if (!SpvType) {
349 const Type *LLVMFPTy = Type::getFloatTy(Ctx);
350 SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
351 }
352 // Find a constant in DT or build a new one.
353 const auto ConstFP = ConstantFP::get(Ctx, Val);
354 Register Res = DT.find(ConstFP, &MF);
355 if (!Res.isValid()) {
356 Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(32));
357 MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
358 assignSPIRVTypeToVReg(SpvType, Res, MF);
359 DT.add(ConstFP, &MF, Res);
360
362 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
363 .addDef(Res)
364 .addUse(getSPIRVTypeID(SpvType));
365 addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
366 }
367
368 return Res;
369}
370
371Register SPIRVGlobalRegistry::getOrCreateBaseRegister(
372 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
373 const SPIRVInstrInfo &TII, unsigned BitWidth, bool ZeroAsNull) {
374 SPIRVType *Type = SpvType;
375 if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
376 SpvType->getOpcode() == SPIRV::OpTypeArray) {
377 auto EleTypeReg = SpvType->getOperand(1).getReg();
378 Type = getSPIRVTypeForVReg(EleTypeReg);
379 }
380 if (Type->getOpcode() == SPIRV::OpTypeFloat) {
382 return getOrCreateConstFP(dyn_cast<ConstantFP>(Val)->getValue(), I,
383 SpvBaseType, TII, ZeroAsNull);
384 }
385 assert(Type->getOpcode() == SPIRV::OpTypeInt);
388 SpvBaseType, TII, ZeroAsNull);
389}
390
391Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
392 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
393 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
394 unsigned ElemCnt, bool ZeroAsNull) {
395 // Find a constant vector or array in DT or build a new one.
396 Register Res = DT.find(CA, CurMF);
397 // If no values are attached, the composite is null constant.
398 bool IsNull = Val->isNullValue() && ZeroAsNull;
399 if (!Res.isValid()) {
400 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
401 // error on validation.
402 // TODO: can moved below once sorting of types/consts/defs is implemented.
403 Register SpvScalConst;
404 if (!IsNull)
405 SpvScalConst =
406 getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
407
408 // TODO: handle cases where the type is not 32bit wide
409 // TODO: https://github.com/llvm/llvm-project/issues/88129
410 LLT LLTy = LLT::scalar(32);
411 Register SpvVecConst =
413 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass);
414 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
415 DT.add(CA, CurMF, SpvVecConst);
417 MachineBasicBlock &BB = *I.getParent();
418 if (!IsNull) {
419 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
420 .addDef(SpvVecConst)
421 .addUse(getSPIRVTypeID(SpvType));
422 for (unsigned i = 0; i < ElemCnt; ++i)
423 MIB.addUse(SpvScalConst);
424 } else {
425 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
426 .addDef(SpvVecConst)
427 .addUse(getSPIRVTypeID(SpvType));
428 }
429 const auto &Subtarget = CurMF->getSubtarget();
430 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
431 *Subtarget.getRegisterInfo(),
432 *Subtarget.getRegBankInfo());
433 return SpvVecConst;
434 }
435 return Res;
436}
437
440 SPIRVType *SpvType,
441 const SPIRVInstrInfo &TII,
442 bool ZeroAsNull) {
443 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
444 assert(LLVMTy->isVectorTy());
445 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
446 Type *LLVMBaseTy = LLVMVecTy->getElementType();
447 assert(LLVMBaseTy->isIntegerTy());
448 auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
449 auto *ConstVec =
450 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
451 unsigned BW = getScalarOrVectorBitWidth(SpvType);
452 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
453 SpvType->getOperand(2).getImm(),
454 ZeroAsNull);
455}
456
459 SPIRVType *SpvType,
460 const SPIRVInstrInfo &TII,
461 bool ZeroAsNull) {
462 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
463 assert(LLVMTy->isVectorTy());
464 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
465 Type *LLVMBaseTy = LLVMVecTy->getElementType();
466 assert(LLVMBaseTy->isFloatingPointTy());
467 auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
468 auto *ConstVec =
469 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
470 unsigned BW = getScalarOrVectorBitWidth(SpvType);
471 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
472 SpvType->getOperand(2).getImm(),
473 ZeroAsNull);
474}
475
477 uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,
478 const SPIRVInstrInfo &TII) {
479 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
480 assert(LLVMTy->isArrayTy());
481 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
482 Type *LLVMBaseTy = LLVMArrTy->getElementType();
483 Constant *CI = ConstantInt::get(LLVMBaseTy, Val);
484 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
485 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
486 // The following is reasonably unique key that is better that [Val]. The naive
487 // alternative would be something along the lines of:
488 // SmallVector<Constant *> NumCI(Num, CI);
489 // Constant *UniqueKey =
490 // ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);
491 // that would be a truly unique but dangerous key, because it could lead to
492 // the creation of constants of arbitrary length (that is, the parameter of
493 // memset) which were missing in the original module.
495 {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),
496 ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});
497 return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,
498 LLVMArrTy->getNumElements());
499}
500
501Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
502 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
503 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
504 Register Res = DT.find(CA, CurMF);
505 if (!Res.isValid()) {
506 Register SpvScalConst;
507 if (Val || EmitIR) {
508 SPIRVType *SpvBaseType =
510 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
511 }
512 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
513 Register SpvVecConst =
515 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass);
516 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
517 DT.add(CA, CurMF, SpvVecConst);
518 if (EmitIR) {
519 MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
520 } else {
521 if (Val) {
522 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
523 .addDef(SpvVecConst)
524 .addUse(getSPIRVTypeID(SpvType));
525 for (unsigned i = 0; i < ElemCnt; ++i)
526 MIB.addUse(SpvScalConst);
527 } else {
528 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
529 .addDef(SpvVecConst)
530 .addUse(getSPIRVTypeID(SpvType));
531 }
532 }
533 return SpvVecConst;
534 }
535 return Res;
536}
537
540 MachineIRBuilder &MIRBuilder,
541 SPIRVType *SpvType, bool EmitIR) {
542 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
543 assert(LLVMTy->isVectorTy());
544 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
545 Type *LLVMBaseTy = LLVMVecTy->getElementType();
546 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
547 auto ConstVec =
548 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
549 unsigned BW = getScalarOrVectorBitWidth(SpvType);
550 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
551 ConstVec, BW,
552 SpvType->getOperand(2).getImm());
553}
554
557 SPIRVType *SpvType) {
558 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
559 const TypedPointerType *LLVMPtrTy = cast<TypedPointerType>(LLVMTy);
560 // Find a constant in DT or build a new one.
562 LLVMPtrTy->getElementType(), LLVMPtrTy->getAddressSpace()));
563 Register Res = DT.find(CP, CurMF);
564 if (!Res.isValid()) {
565 LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
567 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
568 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
569 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
570 .addDef(Res)
571 .addUse(getSPIRVTypeID(SpvType));
572 DT.add(CP, CurMF, Res);
573 }
574 return Res;
575}
576
578 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
579 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
580 SPIRVType *SampTy;
581 if (SpvType)
582 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
583 else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t",
584 MIRBuilder)) == nullptr)
585 report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
586
587 auto Sampler =
588 ResReg.isValid()
589 ? ResReg
590 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
591 auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
592 .addDef(Sampler)
593 .addUse(getSPIRVTypeID(SampTy))
595 .addImm(Param)
596 .addImm(FilerMode);
597 assert(Res->getOperand(0).isReg());
598 return Res->getOperand(0).getReg();
599}
600
603 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
604 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
605 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
606 bool IsInstSelector) {
607 const GlobalVariable *GVar = nullptr;
608 if (GV)
609 GVar = cast<const GlobalVariable>(GV);
610 else {
611 // If GV is not passed explicitly, use the name to find or construct
612 // the global variable.
613 Module *M = MIRBuilder.getMF().getFunction().getParent();
614 GVar = M->getGlobalVariable(Name);
615 if (GVar == nullptr) {
616 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
617 // Module takes ownership of the global var.
618 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
620 Twine(Name));
621 }
622 GV = GVar;
623 }
624 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
625 if (Reg.isValid()) {
626 if (Reg != ResVReg)
627 MIRBuilder.buildCopy(ResVReg, Reg);
628 return ResVReg;
629 }
630
631 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
632 .addDef(ResVReg)
634 .addImm(static_cast<uint32_t>(Storage));
635
636 if (Init != 0) {
637 MIB.addUse(Init->getOperand(0).getReg());
638 }
639
640 // ISel may introduce a new register on this step, so we need to add it to
641 // DT and correct its type avoiding fails on the next stage.
642 if (IsInstSelector) {
643 const auto &Subtarget = CurMF->getSubtarget();
644 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
645 *Subtarget.getRegisterInfo(),
646 *Subtarget.getRegBankInfo());
647 }
648 Reg = MIB->getOperand(0).getReg();
649 DT.add(GVar, &MIRBuilder.getMF(), Reg);
650
651 // Set to Reg the same type as ResVReg has.
652 auto MRI = MIRBuilder.getMRI();
653 assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
654 if (Reg != ResVReg) {
655 LLT RegLLTy =
656 LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
657 MRI->setType(Reg, RegLLTy);
658 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
659 } else {
660 // Our knowledge about the type may be updated.
661 // If that's the case, we need to update a type
662 // associated with the register.
663 SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
664 if (!DefType || DefType != BaseType)
665 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
666 }
667
668 // If it's a global variable with name, output OpName for it.
669 if (GVar && GVar->hasName())
670 buildOpName(Reg, GVar->getName(), MIRBuilder);
671
672 // Output decorations for the GV.
673 // TODO: maybe move to GenerateDecorations pass.
674 const SPIRVSubtarget &ST =
675 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
676 if (IsConst && ST.isOpenCLEnv())
677 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
678
679 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
680 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
681 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
682 }
683
684 if (HasLinkageTy)
685 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
686 {static_cast<uint32_t>(LinkageType)}, Name);
687
688 SPIRV::BuiltIn::BuiltIn BuiltInId;
689 if (getSpirvBuiltInIdByName(Name, BuiltInId))
690 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
691 {static_cast<uint32_t>(BuiltInId)});
692
693 // If it's a global variable with "spirv.Decorations" metadata node
694 // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
695 // arguments.
696 MDNode *GVarMD = nullptr;
697 if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
698 buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD);
699
700 return Reg;
701}
702
703SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
704 SPIRVType *ElemType,
705 MachineIRBuilder &MIRBuilder,
706 bool EmitIR) {
707 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
708 "Invalid array element type");
709 Register NumElementsVReg =
710 buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
711 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
712 .addDef(createTypeVReg(MIRBuilder))
713 .addUse(getSPIRVTypeID(ElemType))
714 .addUse(NumElementsVReg);
715 return MIB;
716}
717
718SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
719 MachineIRBuilder &MIRBuilder) {
720 assert(Ty->hasName());
721 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
722 Register ResVReg = createTypeVReg(MIRBuilder);
723 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
724 addStringImm(Name, MIB);
725 buildOpName(ResVReg, Name, MIRBuilder);
726 return MIB;
727}
728
729SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
730 MachineIRBuilder &MIRBuilder,
731 bool EmitIR) {
732 SmallVector<Register, 4> FieldTypes;
733 for (const auto &Elem : Ty->elements()) {
734 SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder);
735 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
736 "Invalid struct element type");
737 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
738 }
739 Register ResVReg = createTypeVReg(MIRBuilder);
740 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
741 for (const auto &Ty : FieldTypes)
742 MIB.addUse(Ty);
743 if (Ty->hasName())
744 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
745 if (Ty->isPacked())
746 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
747 return MIB;
748}
749
750SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
751 const Type *Ty, MachineIRBuilder &MIRBuilder,
752 SPIRV::AccessQualifier::AccessQualifier AccQual) {
753 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
754 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
755}
756
757SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
758 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
759 MachineIRBuilder &MIRBuilder, Register Reg) {
760 if (!Reg.isValid())
761 Reg = createTypeVReg(MIRBuilder);
762 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
763 .addDef(Reg)
764 .addImm(static_cast<uint32_t>(SC))
765 .addUse(getSPIRVTypeID(ElemType));
766}
767
768SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
769 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
770 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
771 .addUse(createTypeVReg(MIRBuilder))
772 .addImm(static_cast<uint32_t>(SC));
773}
774
775SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
776 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
777 MachineIRBuilder &MIRBuilder) {
778 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
779 .addDef(createTypeVReg(MIRBuilder))
780 .addUse(getSPIRVTypeID(RetType));
781 for (const SPIRVType *ArgType : ArgTypes)
782 MIB.addUse(getSPIRVTypeID(ArgType));
783 return MIB;
784}
785
787 const Type *Ty, SPIRVType *RetType,
788 const SmallVectorImpl<SPIRVType *> &ArgTypes,
789 MachineIRBuilder &MIRBuilder) {
790 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
791 if (Reg.isValid())
792 return getSPIRVTypeForVReg(Reg);
793 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
794 DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
795 return finishCreatingSPIRVType(Ty, SpirvType);
796}
797
798SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
799 const Type *Ty, MachineIRBuilder &MIRBuilder,
800 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
801 Ty = adjustIntTypeByWidth(Ty);
802 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
803 if (Reg.isValid())
804 return getSPIRVTypeForVReg(Reg);
805 if (ForwardPointerTypes.contains(Ty))
806 return ForwardPointerTypes[Ty];
807 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
808}
809
811 assert(SpirvType && "Attempting to get type id for nullptr type.");
812 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
813 return SpirvType->uses().begin()->getReg();
814 return SpirvType->defs().begin()->getReg();
815}
816
817// We need to use a new LLVM integer type if there is a mismatch between
818// number of bits in LLVM and SPIRV integer types to let DuplicateTracker
819// ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without
820// such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the
821// same "OpTypeInt 8" type for a series of LLVM integer types with number of
822// bits less than 8. This would lead to duplicate type definitions
823// eventually due to the method that DuplicateTracker utilizes to reason
824// about uniqueness of type records.
825const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {
826 if (auto IType = dyn_cast<IntegerType>(Ty)) {
827 unsigned SrcBitWidth = IType->getBitWidth();
828 if (SrcBitWidth > 1) {
829 unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);
830 // Maybe change source LLVM type to keep DuplicateTracker consistent.
831 if (SrcBitWidth != BitWidth)
833 }
834 }
835 return Ty;
836}
837
838SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
839 const Type *Ty, MachineIRBuilder &MIRBuilder,
840 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
841 if (isSpecialOpaqueType(Ty))
842 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
843 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
844 auto t = TypeToSPIRVTypeMap.find(Ty);
845 if (t != TypeToSPIRVTypeMap.end()) {
846 auto tt = t->second.find(&MIRBuilder.getMF());
847 if (tt != t->second.end())
848 return getSPIRVTypeForVReg(tt->second);
849 }
850
851 if (auto IType = dyn_cast<IntegerType>(Ty)) {
852 const unsigned Width = IType->getBitWidth();
853 return Width == 1 ? getOpTypeBool(MIRBuilder)
854 : getOpTypeInt(Width, MIRBuilder, false);
855 }
856 if (Ty->isFloatingPointTy())
857 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
858 if (Ty->isVoidTy())
859 return getOpTypeVoid(MIRBuilder);
860 if (Ty->isVectorTy()) {
861 SPIRVType *El =
862 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
863 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
864 MIRBuilder);
865 }
866 if (Ty->isArrayTy()) {
867 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
868 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
869 }
870 if (auto SType = dyn_cast<StructType>(Ty)) {
871 if (SType->isOpaque())
872 return getOpTypeOpaque(SType, MIRBuilder);
873 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
874 }
875 if (auto FType = dyn_cast<FunctionType>(Ty)) {
876 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
878 for (const auto &t : FType->params()) {
879 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
880 }
881 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
882 }
883 unsigned AddrSpace = 0xFFFF;
884 if (auto PType = dyn_cast<TypedPointerType>(Ty))
885 AddrSpace = PType->getAddressSpace();
886 else if (auto PType = dyn_cast<PointerType>(Ty))
887 AddrSpace = PType->getAddressSpace();
888 else
889 report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
890
891 SPIRVType *SpvElementType = nullptr;
892 if (auto PType = dyn_cast<TypedPointerType>(Ty))
893 SpvElementType = getOrCreateSPIRVType(PType->getElementType(), MIRBuilder,
894 AccQual, EmitIR);
895 else
896 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
897
898 // Get access to information about available extensions
899 const SPIRVSubtarget *ST =
900 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
901 auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
902 // Null pointer means we have a loop in type definitions, make and
903 // return corresponding OpTypeForwardPointer.
904 if (SpvElementType == nullptr) {
905 if (!ForwardPointerTypes.contains(Ty))
906 ForwardPointerTypes[Ty] = getOpTypeForwardPointer(SC, MIRBuilder);
907 return ForwardPointerTypes[Ty];
908 }
909 // If we have forward pointer associated with this type, use its register
910 // operand to create OpTypePointer.
911 if (ForwardPointerTypes.contains(Ty)) {
912 Register Reg = getSPIRVTypeID(ForwardPointerTypes[Ty]);
913 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
914 }
915
916 return getOrCreateSPIRVPointerType(SpvElementType, MIRBuilder, SC);
917}
918
919SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
920 const Type *Ty, MachineIRBuilder &MIRBuilder,
921 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
922 if (TypesInProcessing.count(Ty) && !isPointerTy(Ty))
923 return nullptr;
924 TypesInProcessing.insert(Ty);
925 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
926 TypesInProcessing.erase(Ty);
927 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
928 SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
929 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
930 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
931 // will be added later. For special types it is already added to DT.
932 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
933 !isSpecialOpaqueType(Ty)) {
934 if (!isPointerTy(Ty))
935 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
936 else if (isTypedPointerTy(Ty))
937 DT.add(cast<TypedPointerType>(Ty)->getElementType(),
938 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
939 getSPIRVTypeID(SpirvType));
940 else
941 DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
942 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
943 getSPIRVTypeID(SpirvType));
944 }
945
946 return SpirvType;
947}
948
949SPIRVType *
951 const MachineFunction *MF) const {
952 auto t = VRegToTypeMap.find(MF ? MF : CurMF);
953 if (t != VRegToTypeMap.end()) {
954 auto tt = t->second.find(VReg);
955 if (tt != t->second.end())
956 return tt->second;
957 }
958 return nullptr;
959}
960
962 const Type *Ty, MachineIRBuilder &MIRBuilder,
963 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
964 Register Reg;
965 if (!isPointerTy(Ty)) {
966 Ty = adjustIntTypeByWidth(Ty);
967 Reg = DT.find(Ty, &MIRBuilder.getMF());
968 } else if (isTypedPointerTy(Ty)) {
969 Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(),
970 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
971 } else {
972 Reg =
973 DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
974 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
975 }
976
977 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
978 return getSPIRVTypeForVReg(Reg);
979 TypesInProcessing.clear();
980 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
981 // Create normal pointer types for the corresponding OpTypeForwardPointers.
982 for (auto &CU : ForwardPointerTypes) {
983 const Type *Ty2 = CU.first;
984 SPIRVType *STy2 = CU.second;
985 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
986 STy2 = getSPIRVTypeForVReg(Reg);
987 else
988 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
989 if (Ty == Ty2)
990 STy = STy2;
991 }
992 ForwardPointerTypes.clear();
993 return STy;
994}
995
997 unsigned TypeOpcode) const {
999 assert(Type && "isScalarOfType VReg has no type assigned");
1000 return Type->getOpcode() == TypeOpcode;
1001}
1002
1004 unsigned TypeOpcode) const {
1006 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
1007 if (Type->getOpcode() == TypeOpcode)
1008 return true;
1009 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1010 Register ScalarTypeVReg = Type->getOperand(1).getReg();
1011 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
1012 return ScalarType->getOpcode() == TypeOpcode;
1013 }
1014 return false;
1015}
1016
1017unsigned
1020}
1021
1022unsigned
1024 if (!Type)
1025 return 0;
1026 return Type->getOpcode() == SPIRV::OpTypeVector
1027 ? static_cast<unsigned>(Type->getOperand(2).getImm())
1028 : 1;
1029}
1030
1031unsigned
1033 assert(Type && "Invalid Type pointer");
1034 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1035 auto EleTypeReg = Type->getOperand(1).getReg();
1036 Type = getSPIRVTypeForVReg(EleTypeReg);
1037 }
1038 if (Type->getOpcode() == SPIRV::OpTypeInt ||
1039 Type->getOpcode() == SPIRV::OpTypeFloat)
1040 return Type->getOperand(1).getImm();
1041 if (Type->getOpcode() == SPIRV::OpTypeBool)
1042 return 1;
1043 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
1044}
1045
1047 const SPIRVType *Type) const {
1048 assert(Type && "Invalid Type pointer");
1049 unsigned NumElements = 1;
1050 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1051 NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1052 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1053 }
1054 return Type->getOpcode() == SPIRV::OpTypeInt ||
1055 Type->getOpcode() == SPIRV::OpTypeFloat
1056 ? NumElements * Type->getOperand(1).getImm()
1057 : 0;
1058}
1059
1061 const SPIRVType *Type) const {
1062 if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1063 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1064 return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1065}
1066
1069 return IntType && IntType->getOperand(2).getImm() != 0;
1070}
1071
1073 return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1074 ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1075 : nullptr;
1076}
1077
1079 SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));
1080 return ElemType ? ElemType->getOpcode() : 0;
1081}
1082
1084 const SPIRVType *Type2) const {
1085 if (!Type1 || !Type2)
1086 return false;
1087 auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1088 // Ignore difference between <1.5 and >=1.5 protocol versions:
1089 // it's valid if either Result Type or Operand is a pointer, and the other
1090 // is a pointer, an integer scalar, or an integer vector.
1091 if (Op1 == SPIRV::OpTypePointer &&
1092 (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1093 return true;
1094 if (Op2 == SPIRV::OpTypePointer &&
1095 (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1096 return true;
1097 unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1099 return Bits1 > 0 && Bits1 == Bits2;
1100}
1101
1102SPIRV::StorageClass::StorageClass
1105 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
1106 Type->getOperand(1).isImm() && "Pointer type is expected");
1107 return static_cast<SPIRV::StorageClass::StorageClass>(
1108 Type->getOperand(1).getImm());
1109}
1110
1112 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1113 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1114 SPIRV::ImageFormat::ImageFormat ImageFormat,
1115 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1116 auto TD = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
1117 Depth, Arrayed, Multisampled, Sampled,
1118 ImageFormat, AccessQual);
1119 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1120 return Res;
1121 Register ResVReg = createTypeVReg(MIRBuilder);
1122 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1123 return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1124 .addDef(ResVReg)
1125 .addUse(getSPIRVTypeID(SampledType))
1126 .addImm(Dim)
1127 .addImm(Depth) // Depth (whether or not it is a Depth image).
1128 .addImm(Arrayed) // Arrayed.
1129 .addImm(Multisampled) // Multisampled (0 = only single-sample).
1130 .addImm(Sampled) // Sampled (0 = usage known at runtime).
1131 .addImm(ImageFormat)
1132 .addImm(AccessQual);
1133}
1134
1135SPIRVType *
1137 auto TD = SPIRV::make_descr_sampler();
1138 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1139 return Res;
1140 Register ResVReg = createTypeVReg(MIRBuilder);
1141 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1142 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
1143}
1144
1146 MachineIRBuilder &MIRBuilder,
1147 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1148 auto TD = SPIRV::make_descr_pipe(AccessQual);
1149 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1150 return Res;
1151 Register ResVReg = createTypeVReg(MIRBuilder);
1152 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1153 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1154 .addDef(ResVReg)
1155 .addImm(AccessQual);
1156}
1157
1159 MachineIRBuilder &MIRBuilder) {
1160 auto TD = SPIRV::make_descr_event();
1161 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1162 return Res;
1163 Register ResVReg = createTypeVReg(MIRBuilder);
1164 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1165 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
1166}
1167
1169 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1171 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1172 ImageType->getOperand(1).getReg())),
1173 ImageType);
1174 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1175 return Res;
1176 Register ResVReg = createTypeVReg(MIRBuilder);
1177 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1178 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1179 .addDef(ResVReg)
1180 .addUse(getSPIRVTypeID(ImageType));
1181}
1182
1184 MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
1185 const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
1186 uint32_t Use) {
1187 Register ResVReg = DT.find(ExtensionType, &MIRBuilder.getMF());
1188 if (ResVReg.isValid())
1189 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1190 ResVReg = createTypeVReg(MIRBuilder);
1191 SPIRVType *SpirvTy =
1192 MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
1193 .addDef(ResVReg)
1194 .addUse(getSPIRVTypeID(ElemType))
1195 .addUse(buildConstantInt(Scope, MIRBuilder, nullptr, true))
1196 .addUse(buildConstantInt(Rows, MIRBuilder, nullptr, true))
1197 .addUse(buildConstantInt(Columns, MIRBuilder, nullptr, true))
1198 .addUse(buildConstantInt(Use, MIRBuilder, nullptr, true));
1199 DT.add(ExtensionType, &MIRBuilder.getMF(), ResVReg);
1200 return SpirvTy;
1201}
1202
1204 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1205 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
1206 if (ResVReg.isValid())
1207 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1208 ResVReg = createTypeVReg(MIRBuilder);
1209 SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
1210 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
1211 return SpirvTy;
1212}
1213
1214const MachineInstr *
1215SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
1216 MachineIRBuilder &MIRBuilder) {
1217 Register Reg = DT.find(TD, &MIRBuilder.getMF());
1218 if (Reg.isValid())
1219 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
1220 return nullptr;
1221}
1222
1223// Returns nullptr if unable to recognize SPIRV type name
1225 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
1226 SPIRV::StorageClass::StorageClass SC,
1227 SPIRV::AccessQualifier::AccessQualifier AQ) {
1228 unsigned VecElts = 0;
1229 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1230
1231 // Parse strings representing either a SPIR-V or OpenCL builtin type.
1232 if (hasBuiltinTypePrefix(TypeStr))
1234 TypeStr.str(), MIRBuilder.getContext()),
1235 MIRBuilder, AQ);
1236
1237 // Parse type name in either "typeN" or "type vector[N]" format, where
1238 // N is the number of elements of the vector.
1239 Type *Ty;
1240
1241 Ty = parseBasicTypeName(TypeStr, Ctx);
1242 if (!Ty)
1243 // Unable to recognize SPIRV type name
1244 return nullptr;
1245
1246 auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
1247
1248 // Handle "type*" or "type* vector[N]".
1249 if (TypeStr.starts_with("*")) {
1250 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1251 TypeStr = TypeStr.substr(strlen("*"));
1252 }
1253
1254 // Handle "typeN*" or "type vector[N]*".
1255 bool IsPtrToVec = TypeStr.consume_back("*");
1256
1257 if (TypeStr.consume_front(" vector[")) {
1258 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1259 }
1260 TypeStr.getAsInteger(10, VecElts);
1261 if (VecElts > 0)
1262 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
1263
1264 if (IsPtrToVec)
1265 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1266
1267 return SpirvTy;
1268}
1269
1270SPIRVType *
1272 MachineIRBuilder &MIRBuilder) {
1273 return getOrCreateSPIRVType(
1275 MIRBuilder);
1276}
1277
1278SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1279 SPIRVType *SpirvType) {
1280 assert(CurMF == SpirvType->getMF());
1281 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1282 SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);
1283 return SpirvType;
1284}
1285
1287 MachineInstr &I,
1288 const SPIRVInstrInfo &TII,
1289 unsigned SPIRVOPcode,
1290 Type *LLVMTy) {
1291 Register Reg = DT.find(LLVMTy, CurMF);
1292 if (Reg.isValid())
1293 return getSPIRVTypeForVReg(Reg);
1294 MachineBasicBlock &BB = *I.getParent();
1295 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRVOPcode))
1298 .addImm(0);
1299 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1300 return finishCreatingSPIRVType(LLVMTy, MIB);
1301}
1302
1304 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1305 // Maybe adjust bit width to keep DuplicateTracker consistent. Without
1306 // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for
1307 // example, the same "OpTypeInt 8" type for a series of LLVM integer types
1308 // with number of bits less than 8, causing duplicate type definitions.
1309 BitWidth = adjustOpTypeIntWidth(BitWidth);
1311 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1312}
1313
1315 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1317 Type *LLVMTy;
1318 switch (BitWidth) {
1319 case 16:
1320 LLVMTy = Type::getHalfTy(Ctx);
1321 break;
1322 case 32:
1323 LLVMTy = Type::getFloatTy(Ctx);
1324 break;
1325 case 64:
1326 LLVMTy = Type::getDoubleTy(Ctx);
1327 break;
1328 default:
1329 llvm_unreachable("Bit width is of unexpected size.");
1330 }
1331 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1332}
1333
1334SPIRVType *
1336 return getOrCreateSPIRVType(
1337 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1338 MIRBuilder);
1339}
1340
1341SPIRVType *
1343 const SPIRVInstrInfo &TII) {
1345 Register Reg = DT.find(LLVMTy, CurMF);
1346 if (Reg.isValid())
1347 return getSPIRVTypeForVReg(Reg);
1348 MachineBasicBlock &BB = *I.getParent();
1349 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1351 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1352 return finishCreatingSPIRVType(LLVMTy, MIB);
1353}
1354
1356 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1357 return getOrCreateSPIRVType(
1359 NumElements),
1360 MIRBuilder);
1361}
1362
1364 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1365 const SPIRVInstrInfo &TII) {
1366 Type *LLVMTy = FixedVectorType::get(
1367 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1368 Register Reg = DT.find(LLVMTy, CurMF);
1369 if (Reg.isValid())
1370 return getSPIRVTypeForVReg(Reg);
1371 MachineBasicBlock &BB = *I.getParent();
1372 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1375 .addImm(NumElements);
1376 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1377 return finishCreatingSPIRVType(LLVMTy, MIB);
1378}
1379
1381 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1382 const SPIRVInstrInfo &TII) {
1383 Type *LLVMTy = ArrayType::get(
1384 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1385 Register Reg = DT.find(LLVMTy, CurMF);
1386 if (Reg.isValid())
1387 return getSPIRVTypeForVReg(Reg);
1388 MachineBasicBlock &BB = *I.getParent();
1389 SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1390 Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1391 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1394 .addUse(Len);
1395 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1396 return finishCreatingSPIRVType(LLVMTy, MIB);
1397}
1398
1400 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1401 SPIRV::StorageClass::StorageClass SC) {
1402 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1404 Type *LLVMTy = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1405 AddressSpace);
1406 // check if this type is already available
1407 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1408 if (Reg.isValid())
1409 return getSPIRVTypeForVReg(Reg);
1410 // create a new type
1411 auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1412 MIRBuilder.getDebugLoc(),
1413 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1415 .addImm(static_cast<uint32_t>(SC))
1417 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1418 return finishCreatingSPIRVType(LLVMTy, MIB);
1419}
1420
1423 SPIRV::StorageClass::StorageClass SC) {
1424 MachineIRBuilder MIRBuilder(I);
1425 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1426}
1427
1429 SPIRVType *SpvType,
1430 const SPIRVInstrInfo &TII) {
1431 assert(SpvType);
1432 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1433 assert(LLVMTy);
1434 // Find a constant in DT or build a new one.
1435 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1436 Register Res = DT.find(UV, CurMF);
1437 if (Res.isValid())
1438 return Res;
1439 LLT LLTy = LLT::scalar(32);
1441 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
1442 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1443 DT.add(UV, CurMF, Res);
1444
1446 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1447 .addDef(Res)
1448 .addUse(getSPIRVTypeID(SpvType));
1449 const auto &ST = CurMF->getSubtarget();
1450 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1451 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1452 return Res;
1453}
unsigned const MachineRegisterInfo * MRI
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
return RetTy
std::string Name
ELFYAML::ELF_REL Type2
Definition: ELFYAML.cpp:1829
const HexagonInstrInfo * TII
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
static Register createTypeVReg(MachineIRBuilder &MIRBuilder)
APInt bitcastToAPInt() const
Definition: APFloat.h:1266
bool isPosZero() const
Definition: APFloat.h:1371
Class for arbitrary precision integers.
Definition: APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1498
int64_t getSExtValue() const
Get sign extended value.
Definition: APInt.h:1520
Class to represent array types.
Definition: DerivedTypes.h:371
uint64_t getNumElements() const
Definition: DerivedTypes.h:383
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:635
Type * getElementType() const
Definition: DerivedTypes.h:384
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:269
const APFloat & getValueAPF() const
Definition: Constants.h:312
This is the shared class of boolean and integer constants.
Definition: Constants.h:81
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1800
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition: Constants.h:477
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1450
This is an important base class in LLVM.
Definition: Constant.h:42
const APInt & getUniqueInteger() const
If C is a constant integer then return its value, otherwise C must be a vector of constant integers,...
Definition: Constants.cpp:1745
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition: Constants.cpp:90
Class to represent fixed width SIMD vectors.
Definition: DerivedTypes.h:539
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:680
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:380
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:80
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
Definition: Value.h:565
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:656
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
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:266
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:57
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:100
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
Metadata node.
Definition: Metadata.h:1069
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.
LLVMContext & getContext() const
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Val)
Build and insert Res = G_SPLAT_VECTOR Val.
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:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:569
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:733
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:722
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:579
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
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1852
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)
unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * assignFloatTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
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)
Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR=true)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII)
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
SPIRVGlobalRegistry(unsigned PointerSize)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
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)
unsigned getPointeeTypeOp(Register PtrReg)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
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
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
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 getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:640
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:455
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:215
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:556
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:250
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:620
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:282
Class to represent struct types.
Definition: DerivedTypes.h:216
ArrayRef< Type * > elements() const
Definition: DerivedTypes.h:333
bool isPacked() const
Definition: DerivedTypes.h:278
bool hasName() const
Return true if this is a named struct that has a non-empty name.
Definition: DerivedTypes.h:304
StringRef getName() const
Return the name for this struct type if it has an identity.
Definition: Type.cpp:578
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:720
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)
static Type * getDoubleTy(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:261
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:248
Type * getArrayElementType() const
Definition: Type.h:399
uint64_t getArrayNumElements() const
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
static IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:184
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:224
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:139
A few GPU targets, such as DXIL and SPIR-V, have typed pointers.
Type * getElementType() const
static TypedPointerType * 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.
'undef' values are things that do not have specified contents.
Definition: Constants.h:1398
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1833
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
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:641
Type * getElementType() const
Definition: DerivedTypes.h:436
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
SpecialTypeDescriptor make_descr_pipe(uint8_t AQ)
SpecialTypeDescriptor make_descr_sampler()
std::tuple< const Type *, unsigned, unsigned > SpecialTypeDescriptor
SpecialTypeDescriptor make_descr_event()
SpecialTypeDescriptor make_descr_image(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
SpecialTypeDescriptor make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy)
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:100
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:166
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned getPointerAddressSpace(const Type *T)
Definition: SPIRVUtils.h:126
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:80
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:155
AddressSpace
Definition: NVPTXBaseInfo.h:21
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
bool isTypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:110
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:117
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:208
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:383
bool isPointerTy(const Type *T)
Definition: SPIRVUtils.h:120
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
const Type * unifyPtrType(const Type *Ty)
Definition: SPIRVUtils.h:235
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:190
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Definition: SPIRVUtils.cpp:404
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:191
bool hasBuiltinTypePrefix(StringRef Name)
Definition: SPIRVUtils.cpp:376
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:51
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:136
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