LLVM 19.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
93SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width,
94 MachineIRBuilder &MIRBuilder,
95 bool IsSigned) {
96 assert(Width <= 64 && "Unsupported integer width!");
97 const SPIRVSubtarget &ST =
98 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
99 if (ST.canUseExtension(
100 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
101 MIRBuilder.buildInstr(SPIRV::OpExtension)
102 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
103 MIRBuilder.buildInstr(SPIRV::OpCapability)
104 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
105 } else if (Width <= 8)
106 Width = 8;
107 else if (Width <= 16)
108 Width = 16;
109 else if (Width <= 32)
110 Width = 32;
111 else if (Width <= 64)
112 Width = 64;
113
114 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
115 .addDef(createTypeVReg(MIRBuilder))
116 .addImm(Width)
117 .addImm(IsSigned ? 1 : 0);
118 return MIB;
119}
120
121SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
122 MachineIRBuilder &MIRBuilder) {
123 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
124 .addDef(createTypeVReg(MIRBuilder))
125 .addImm(Width);
126 return MIB;
127}
128
129SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
130 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
131 .addDef(createTypeVReg(MIRBuilder));
132}
133
134SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
135 SPIRVType *ElemType,
136 MachineIRBuilder &MIRBuilder) {
137 auto EleOpc = ElemType->getOpcode();
138 (void)EleOpc;
139 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
140 EleOpc == SPIRV::OpTypeBool) &&
141 "Invalid vector element type");
142
143 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
144 .addDef(createTypeVReg(MIRBuilder))
145 .addUse(getSPIRVTypeID(ElemType))
146 .addImm(NumElems);
147 return MIB;
148}
149
150std::tuple<Register, ConstantInt *, bool>
151SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
152 MachineIRBuilder *MIRBuilder,
154 const SPIRVInstrInfo *TII) {
155 const IntegerType *LLVMIntTy;
156 if (SpvType)
157 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
158 else
160 bool NewInstr = false;
161 // Find a constant in DT or build a new one.
162 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
163 Register Res = DT.find(CI, CurMF);
164 if (!Res.isValid()) {
165 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
166 // TODO: handle cases where the type is not 32bit wide
167 // TODO: https://github.com/llvm/llvm-project/issues/88129
168 LLT LLTy = LLT::scalar(32);
170 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
171 if (MIRBuilder)
172 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
173 else
175 DT.add(CI, CurMF, Res);
176 NewInstr = true;
177 }
178 return std::make_tuple(Res, CI, NewInstr);
179}
180
181std::tuple<Register, ConstantFP *, bool, unsigned>
182SPIRVGlobalRegistry::getOrCreateConstFloatReg(APFloat Val, SPIRVType *SpvType,
183 MachineIRBuilder *MIRBuilder,
185 const SPIRVInstrInfo *TII) {
186 const Type *LLVMFloatTy;
188 unsigned BitWidth = 32;
189 if (SpvType)
190 LLVMFloatTy = getTypeForSPIRVType(SpvType);
191 else {
192 LLVMFloatTy = Type::getFloatTy(Ctx);
193 if (MIRBuilder)
194 SpvType = getOrCreateSPIRVType(LLVMFloatTy, *MIRBuilder);
195 }
196 bool NewInstr = false;
197 // Find a constant in DT or build a new one.
198 auto *const CI = ConstantFP::get(Ctx, Val);
199 Register Res = DT.find(CI, CurMF);
200 if (!Res.isValid()) {
201 if (SpvType)
203 // TODO: handle cases where the type is not 32bit wide
204 // TODO: https://github.com/llvm/llvm-project/issues/88129
205 LLT LLTy = LLT::scalar(32);
207 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
208 if (MIRBuilder)
209 assignTypeToVReg(LLVMFloatTy, Res, *MIRBuilder);
210 else
212 DT.add(CI, CurMF, Res);
213 NewInstr = true;
214 }
215 return std::make_tuple(Res, CI, NewInstr, BitWidth);
216}
217
219 SPIRVType *SpvType,
220 const SPIRVInstrInfo &TII,
221 bool ZeroAsNull) {
222 assert(SpvType);
223 ConstantFP *CI;
224 Register Res;
225 bool New;
226 unsigned BitWidth;
227 std::tie(Res, CI, New, BitWidth) =
228 getOrCreateConstFloatReg(Val, SpvType, nullptr, &I, &TII);
229 // If we have found Res register which is defined by the passed G_CONSTANT
230 // machine instruction, a new constant instruction should be created.
231 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
232 return Res;
234 MachineBasicBlock &BB = *I.getParent();
235 // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
236 if (Val.isPosZero() && ZeroAsNull) {
237 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
238 .addDef(Res)
239 .addUse(getSPIRVTypeID(SpvType));
240 } else {
241 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantF))
242 .addDef(Res)
243 .addUse(getSPIRVTypeID(SpvType));
244 addNumImm(
246 MIB);
247 }
248 const auto &ST = CurMF->getSubtarget();
249 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
250 *ST.getRegisterInfo(), *ST.getRegBankInfo());
251 return Res;
252}
253
255 SPIRVType *SpvType,
256 const SPIRVInstrInfo &TII,
257 bool ZeroAsNull) {
258 assert(SpvType);
259 ConstantInt *CI;
260 Register Res;
261 bool New;
262 std::tie(Res, CI, New) =
263 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
264 // If we have found Res register which is defined by the passed G_CONSTANT
265 // machine instruction, a new constant instruction should be created.
266 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
267 return Res;
269 MachineBasicBlock &BB = *I.getParent();
270 if (Val || !ZeroAsNull) {
271 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
272 .addDef(Res)
273 .addUse(getSPIRVTypeID(SpvType));
274 addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
275 } else {
276 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
277 .addDef(Res)
278 .addUse(getSPIRVTypeID(SpvType));
279 }
280 const auto &ST = CurMF->getSubtarget();
281 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
282 *ST.getRegisterInfo(), *ST.getRegBankInfo());
283 return Res;
284}
285
287 MachineIRBuilder &MIRBuilder,
288 SPIRVType *SpvType,
289 bool EmitIR) {
290 auto &MF = MIRBuilder.getMF();
291 const IntegerType *LLVMIntTy;
292 if (SpvType)
293 LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
294 else
295 LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
296 // Find a constant in DT or build a new one.
297 const auto ConstInt =
298 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
299 Register Res = DT.find(ConstInt, &MF);
300 if (!Res.isValid()) {
301 unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
302 LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
303 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
304 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
305 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
306 SPIRV::AccessQualifier::ReadWrite, EmitIR);
307 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
308 if (EmitIR) {
309 MIRBuilder.buildConstant(Res, *ConstInt);
310 } else {
312 if (Val) {
313 assert(SpvType);
314 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
315 .addDef(Res)
316 .addUse(getSPIRVTypeID(SpvType));
317 addNumImm(APInt(BitWidth, Val), MIB);
318 } else {
319 assert(SpvType);
320 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
321 .addDef(Res)
322 .addUse(getSPIRVTypeID(SpvType));
323 }
324 const auto &Subtarget = CurMF->getSubtarget();
325 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
326 *Subtarget.getRegisterInfo(),
327 *Subtarget.getRegBankInfo());
328 }
329 }
330 return Res;
331}
332
334 MachineIRBuilder &MIRBuilder,
335 SPIRVType *SpvType) {
336 auto &MF = MIRBuilder.getMF();
337 auto &Ctx = MF.getFunction().getContext();
338 if (!SpvType) {
339 const Type *LLVMFPTy = Type::getFloatTy(Ctx);
340 SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
341 }
342 // Find a constant in DT or build a new one.
343 const auto ConstFP = ConstantFP::get(Ctx, Val);
344 Register Res = DT.find(ConstFP, &MF);
345 if (!Res.isValid()) {
346 Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(32));
347 MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
348 assignSPIRVTypeToVReg(SpvType, Res, MF);
349 DT.add(ConstFP, &MF, Res);
350
352 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
353 .addDef(Res)
354 .addUse(getSPIRVTypeID(SpvType));
355 addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
356 }
357
358 return Res;
359}
360
361Register SPIRVGlobalRegistry::getOrCreateBaseRegister(Constant *Val,
363 SPIRVType *SpvType,
364 const SPIRVInstrInfo &TII,
365 unsigned BitWidth) {
366 SPIRVType *Type = SpvType;
367 if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
368 SpvType->getOpcode() == SPIRV::OpTypeArray) {
369 auto EleTypeReg = SpvType->getOperand(1).getReg();
370 Type = getSPIRVTypeForVReg(EleTypeReg);
371 }
372 if (Type->getOpcode() == SPIRV::OpTypeFloat) {
374 return getOrCreateConstFP(dyn_cast<ConstantFP>(Val)->getValue(), I,
375 SpvBaseType, TII);
376 }
377 assert(Type->getOpcode() == SPIRV::OpTypeInt);
380 SpvBaseType, TII);
381}
382
383Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
384 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
385 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
386 unsigned ElemCnt, bool ZeroAsNull) {
387 // Find a constant vector in DT or build a new one.
388 Register Res = DT.find(CA, CurMF);
389 // If no values are attached, the composite is null constant.
390 bool IsNull = Val->isNullValue() && ZeroAsNull;
391 if (!Res.isValid()) {
392 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
393 // error on validation.
394 // TODO: can moved below once sorting of types/consts/defs is implemented.
395 Register SpvScalConst;
396 if (!IsNull)
397 SpvScalConst = getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth);
398
399 // TODO: handle cases where the type is not 32bit wide
400 // TODO: https://github.com/llvm/llvm-project/issues/88129
401 LLT LLTy = LLT::scalar(32);
402 Register SpvVecConst =
404 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
405 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
406 DT.add(CA, CurMF, SpvVecConst);
408 MachineBasicBlock &BB = *I.getParent();
409 if (!IsNull) {
410 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
411 .addDef(SpvVecConst)
412 .addUse(getSPIRVTypeID(SpvType));
413 for (unsigned i = 0; i < ElemCnt; ++i)
414 MIB.addUse(SpvScalConst);
415 } else {
416 MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
417 .addDef(SpvVecConst)
418 .addUse(getSPIRVTypeID(SpvType));
419 }
420 const auto &Subtarget = CurMF->getSubtarget();
421 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
422 *Subtarget.getRegisterInfo(),
423 *Subtarget.getRegBankInfo());
424 return SpvVecConst;
425 }
426 return Res;
427}
428
431 SPIRVType *SpvType,
432 const SPIRVInstrInfo &TII,
433 bool ZeroAsNull) {
434 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
435 assert(LLVMTy->isVectorTy());
436 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
437 Type *LLVMBaseTy = LLVMVecTy->getElementType();
438 assert(LLVMBaseTy->isIntegerTy());
439 auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
440 auto *ConstVec =
441 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
442 unsigned BW = getScalarOrVectorBitWidth(SpvType);
443 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
444 SpvType->getOperand(2).getImm(),
445 ZeroAsNull);
446}
447
450 SPIRVType *SpvType,
451 const SPIRVInstrInfo &TII,
452 bool ZeroAsNull) {
453 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
454 assert(LLVMTy->isVectorTy());
455 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
456 Type *LLVMBaseTy = LLVMVecTy->getElementType();
457 assert(LLVMBaseTy->isFloatingPointTy());
458 auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
459 auto *ConstVec =
460 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
461 unsigned BW = getScalarOrVectorBitWidth(SpvType);
462 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
463 SpvType->getOperand(2).getImm(),
464 ZeroAsNull);
465}
466
469 SPIRVType *SpvType,
470 const SPIRVInstrInfo &TII) {
471 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
472 assert(LLVMTy->isArrayTy());
473 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
474 Type *LLVMBaseTy = LLVMArrTy->getElementType();
475 auto *ConstInt = ConstantInt::get(LLVMBaseTy, Val);
476 auto *ConstArr =
477 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
478 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
479 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
480 return getOrCreateCompositeOrNull(ConstInt, I, SpvType, TII, ConstArr, BW,
481 LLVMArrTy->getNumElements());
482}
483
484Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
485 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
486 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
487 Register Res = DT.find(CA, CurMF);
488 if (!Res.isValid()) {
489 Register SpvScalConst;
490 if (Val || EmitIR) {
491 SPIRVType *SpvBaseType =
493 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
494 }
495 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
496 Register SpvVecConst =
498 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
499 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
500 DT.add(CA, CurMF, SpvVecConst);
501 if (EmitIR) {
502 MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
503 } else {
504 if (Val) {
505 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
506 .addDef(SpvVecConst)
507 .addUse(getSPIRVTypeID(SpvType));
508 for (unsigned i = 0; i < ElemCnt; ++i)
509 MIB.addUse(SpvScalConst);
510 } else {
511 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
512 .addDef(SpvVecConst)
513 .addUse(getSPIRVTypeID(SpvType));
514 }
515 }
516 return SpvVecConst;
517 }
518 return Res;
519}
520
523 MachineIRBuilder &MIRBuilder,
524 SPIRVType *SpvType, bool EmitIR) {
525 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
526 assert(LLVMTy->isVectorTy());
527 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
528 Type *LLVMBaseTy = LLVMVecTy->getElementType();
529 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
530 auto ConstVec =
531 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
532 unsigned BW = getScalarOrVectorBitWidth(SpvType);
533 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
534 ConstVec, BW,
535 SpvType->getOperand(2).getImm());
536}
537
540 MachineIRBuilder &MIRBuilder,
541 SPIRVType *SpvType, bool EmitIR) {
542 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
543 assert(LLVMTy->isArrayTy());
544 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
545 Type *LLVMBaseTy = LLVMArrTy->getElementType();
546 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
547 auto ConstArr =
548 ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
549 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
550 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
551 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
552 ConstArr, BW,
553 LLVMArrTy->getNumElements());
554}
555
558 SPIRVType *SpvType) {
559 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
560 const TypedPointerType *LLVMPtrTy = cast<TypedPointerType>(LLVMTy);
561 // Find a constant in DT or build a new one.
563 LLVMPtrTy->getElementType(), LLVMPtrTy->getAddressSpace()));
564 Register Res = DT.find(CP, CurMF);
565 if (!Res.isValid()) {
566 LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
568 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
569 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
570 MIRBuilder.buildInstr(SPIRV::OpConstantNull)
571 .addDef(Res)
572 .addUse(getSPIRVTypeID(SpvType));
573 DT.add(CP, CurMF, Res);
574 }
575 return Res;
576}
577
579 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
580 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
581 SPIRVType *SampTy;
582 if (SpvType)
583 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
584 else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t",
585 MIRBuilder)) == nullptr)
586 report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
587
588 auto Sampler =
589 ResReg.isValid()
590 ? ResReg
591 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
592 auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
593 .addDef(Sampler)
594 .addUse(getSPIRVTypeID(SampTy))
596 .addImm(Param)
597 .addImm(FilerMode);
598 assert(Res->getOperand(0).isReg());
599 return Res->getOperand(0).getReg();
600}
601
604 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
605 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
606 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
607 bool IsInstSelector) {
608 const GlobalVariable *GVar = nullptr;
609 if (GV)
610 GVar = cast<const GlobalVariable>(GV);
611 else {
612 // If GV is not passed explicitly, use the name to find or construct
613 // the global variable.
614 Module *M = MIRBuilder.getMF().getFunction().getParent();
615 GVar = M->getGlobalVariable(Name);
616 if (GVar == nullptr) {
617 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
618 // Module takes ownership of the global var.
619 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
621 Twine(Name));
622 }
623 GV = GVar;
624 }
625 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
626 if (Reg.isValid()) {
627 if (Reg != ResVReg)
628 MIRBuilder.buildCopy(ResVReg, Reg);
629 return ResVReg;
630 }
631
632 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
633 .addDef(ResVReg)
635 .addImm(static_cast<uint32_t>(Storage));
636
637 if (Init != 0) {
638 MIB.addUse(Init->getOperand(0).getReg());
639 }
640
641 // ISel may introduce a new register on this step, so we need to add it to
642 // DT and correct its type avoiding fails on the next stage.
643 if (IsInstSelector) {
644 const auto &Subtarget = CurMF->getSubtarget();
645 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
646 *Subtarget.getRegisterInfo(),
647 *Subtarget.getRegBankInfo());
648 }
649 Reg = MIB->getOperand(0).getReg();
650 DT.add(GVar, &MIRBuilder.getMF(), Reg);
651
652 // Set to Reg the same type as ResVReg has.
653 auto MRI = MIRBuilder.getMRI();
654 assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
655 if (Reg != ResVReg) {
656 LLT RegLLTy =
657 LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
658 MRI->setType(Reg, RegLLTy);
659 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
660 } else {
661 // Our knowledge about the type may be updated.
662 // If that's the case, we need to update a type
663 // associated with the register.
664 SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
665 if (!DefType || DefType != BaseType)
666 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
667 }
668
669 // If it's a global variable with name, output OpName for it.
670 if (GVar && GVar->hasName())
671 buildOpName(Reg, GVar->getName(), MIRBuilder);
672
673 // Output decorations for the GV.
674 // TODO: maybe move to GenerateDecorations pass.
675 const SPIRVSubtarget &ST =
676 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
677 if (IsConst && ST.isOpenCLEnv())
678 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
679
680 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
681 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
682 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
683 }
684
685 if (HasLinkageTy)
686 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
687 {static_cast<uint32_t>(LinkageType)}, Name);
688
689 SPIRV::BuiltIn::BuiltIn BuiltInId;
690 if (getSpirvBuiltInIdByName(Name, BuiltInId))
691 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
692 {static_cast<uint32_t>(BuiltInId)});
693
694 // If it's a global variable with "spirv.Decorations" metadata node
695 // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
696 // arguments.
697 MDNode *GVarMD = nullptr;
698 if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
699 buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD);
700
701 return Reg;
702}
703
704SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
705 SPIRVType *ElemType,
706 MachineIRBuilder &MIRBuilder,
707 bool EmitIR) {
708 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
709 "Invalid array element type");
710 Register NumElementsVReg =
711 buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
712 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
713 .addDef(createTypeVReg(MIRBuilder))
714 .addUse(getSPIRVTypeID(ElemType))
715 .addUse(NumElementsVReg);
716 return MIB;
717}
718
719SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
720 MachineIRBuilder &MIRBuilder) {
721 assert(Ty->hasName());
722 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
723 Register ResVReg = createTypeVReg(MIRBuilder);
724 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
725 addStringImm(Name, MIB);
726 buildOpName(ResVReg, Name, MIRBuilder);
727 return MIB;
728}
729
730SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
731 MachineIRBuilder &MIRBuilder,
732 bool EmitIR) {
733 SmallVector<Register, 4> FieldTypes;
734 for (const auto &Elem : Ty->elements()) {
735 SPIRVType *ElemTy =
736 findSPIRVType(toTypedPointer(Elem, Ty->getContext()), MIRBuilder);
737 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
738 "Invalid struct element type");
739 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
740 }
741 Register ResVReg = createTypeVReg(MIRBuilder);
742 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
743 for (const auto &Ty : FieldTypes)
744 MIB.addUse(Ty);
745 if (Ty->hasName())
746 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
747 if (Ty->isPacked())
748 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
749 return MIB;
750}
751
752SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
753 const Type *Ty, MachineIRBuilder &MIRBuilder,
754 SPIRV::AccessQualifier::AccessQualifier AccQual) {
755 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
756 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
757}
758
759SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
760 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
761 MachineIRBuilder &MIRBuilder, Register Reg) {
762 if (!Reg.isValid())
763 Reg = createTypeVReg(MIRBuilder);
764 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
765 .addDef(Reg)
766 .addImm(static_cast<uint32_t>(SC))
767 .addUse(getSPIRVTypeID(ElemType));
768}
769
770SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
771 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
772 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
773 .addUse(createTypeVReg(MIRBuilder))
774 .addImm(static_cast<uint32_t>(SC));
775}
776
777SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
778 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
779 MachineIRBuilder &MIRBuilder) {
780 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
781 .addDef(createTypeVReg(MIRBuilder))
782 .addUse(getSPIRVTypeID(RetType));
783 for (const SPIRVType *ArgType : ArgTypes)
784 MIB.addUse(getSPIRVTypeID(ArgType));
785 return MIB;
786}
787
789 const Type *Ty, SPIRVType *RetType,
790 const SmallVectorImpl<SPIRVType *> &ArgTypes,
791 MachineIRBuilder &MIRBuilder) {
792 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
793 if (Reg.isValid())
794 return getSPIRVTypeForVReg(Reg);
795 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
796 DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
797 return finishCreatingSPIRVType(Ty, SpirvType);
798}
799
800SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
801 const Type *Ty, MachineIRBuilder &MIRBuilder,
802 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
803 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
804 if (Reg.isValid())
805 return getSPIRVTypeForVReg(Reg);
806 if (ForwardPointerTypes.contains(Ty))
807 return ForwardPointerTypes[Ty];
808 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
809}
810
812 assert(SpirvType && "Attempting to get type id for nullptr type.");
813 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
814 return SpirvType->uses().begin()->getReg();
815 return SpirvType->defs().begin()->getReg();
816}
817
818SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
819 const Type *Ty, MachineIRBuilder &MIRBuilder,
820 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
821 if (isSpecialOpaqueType(Ty))
822 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
823 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
824 auto t = TypeToSPIRVTypeMap.find(Ty);
825 if (t != TypeToSPIRVTypeMap.end()) {
826 auto tt = t->second.find(&MIRBuilder.getMF());
827 if (tt != t->second.end())
828 return getSPIRVTypeForVReg(tt->second);
829 }
830
831 if (auto IType = dyn_cast<IntegerType>(Ty)) {
832 const unsigned Width = IType->getBitWidth();
833 return Width == 1 ? getOpTypeBool(MIRBuilder)
834 : getOpTypeInt(Width, MIRBuilder, false);
835 }
836 if (Ty->isFloatingPointTy())
837 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
838 if (Ty->isVoidTy())
839 return getOpTypeVoid(MIRBuilder);
840 if (Ty->isVectorTy()) {
841 SPIRVType *El =
842 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
843 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
844 MIRBuilder);
845 }
846 if (Ty->isArrayTy()) {
847 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
848 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
849 }
850 if (auto SType = dyn_cast<StructType>(Ty)) {
851 if (SType->isOpaque())
852 return getOpTypeOpaque(SType, MIRBuilder);
853 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
854 }
855 if (auto FType = dyn_cast<FunctionType>(Ty)) {
856 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
858 for (const auto &t : FType->params()) {
859 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
860 }
861 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
862 }
863 unsigned AddrSpace = 0xFFFF;
864 if (auto PType = dyn_cast<TypedPointerType>(Ty))
865 AddrSpace = PType->getAddressSpace();
866 else if (auto PType = dyn_cast<PointerType>(Ty))
867 AddrSpace = PType->getAddressSpace();
868 else
869 report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
870
871 SPIRVType *SpvElementType = nullptr;
872 if (auto PType = dyn_cast<TypedPointerType>(Ty))
873 SpvElementType = getOrCreateSPIRVType(PType->getElementType(), MIRBuilder,
874 AccQual, EmitIR);
875 else
876 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
877
878 // Get access to information about available extensions
879 const SPIRVSubtarget *ST =
880 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
881 auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
882 // Null pointer means we have a loop in type definitions, make and
883 // return corresponding OpTypeForwardPointer.
884 if (SpvElementType == nullptr) {
885 if (!ForwardPointerTypes.contains(Ty))
886 ForwardPointerTypes[Ty] = getOpTypeForwardPointer(SC, MIRBuilder);
887 return ForwardPointerTypes[Ty];
888 }
889 // If we have forward pointer associated with this type, use its register
890 // operand to create OpTypePointer.
891 if (ForwardPointerTypes.contains(Ty)) {
892 Register Reg = getSPIRVTypeID(ForwardPointerTypes[Ty]);
893 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
894 }
895
896 return getOrCreateSPIRVPointerType(SpvElementType, MIRBuilder, SC);
897}
898
899SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
900 const Type *Ty, MachineIRBuilder &MIRBuilder,
901 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
902 if (TypesInProcessing.count(Ty) && !isPointerTy(Ty))
903 return nullptr;
904 TypesInProcessing.insert(Ty);
905 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
906 TypesInProcessing.erase(Ty);
907 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
908 SPIRVToLLVMType[SpirvType] = Ty;
909 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
910 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
911 // will be added later. For special types it is already added to DT.
912 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
913 !isSpecialOpaqueType(Ty)) {
914 if (!isPointerTy(Ty))
915 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
916 else if (isTypedPointerTy(Ty))
917 DT.add(cast<TypedPointerType>(Ty)->getElementType(),
918 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
919 getSPIRVTypeID(SpirvType));
920 else
921 DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
922 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
923 getSPIRVTypeID(SpirvType));
924 }
925
926 return SpirvType;
927}
928
929SPIRVType *
931 const MachineFunction *MF) const {
932 auto t = VRegToTypeMap.find(MF ? MF : CurMF);
933 if (t != VRegToTypeMap.end()) {
934 auto tt = t->second.find(VReg);
935 if (tt != t->second.end())
936 return tt->second;
937 }
938 return nullptr;
939}
940
942 const Type *Ty, MachineIRBuilder &MIRBuilder,
943 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
944 Register Reg;
945 if (!isPointerTy(Ty))
946 Reg = DT.find(Ty, &MIRBuilder.getMF());
947 else if (isTypedPointerTy(Ty))
948 Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(),
949 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
950 else
951 Reg =
952 DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
953 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
954
955 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
956 return getSPIRVTypeForVReg(Reg);
957 TypesInProcessing.clear();
958 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
959 // Create normal pointer types for the corresponding OpTypeForwardPointers.
960 for (auto &CU : ForwardPointerTypes) {
961 const Type *Ty2 = CU.first;
962 SPIRVType *STy2 = CU.second;
963 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
964 STy2 = getSPIRVTypeForVReg(Reg);
965 else
966 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
967 if (Ty == Ty2)
968 STy = STy2;
969 }
970 ForwardPointerTypes.clear();
971 return STy;
972}
973
975 unsigned TypeOpcode) const {
977 assert(Type && "isScalarOfType VReg has no type assigned");
978 return Type->getOpcode() == TypeOpcode;
979}
980
982 unsigned TypeOpcode) const {
984 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
985 if (Type->getOpcode() == TypeOpcode)
986 return true;
987 if (Type->getOpcode() == SPIRV::OpTypeVector) {
988 Register ScalarTypeVReg = Type->getOperand(1).getReg();
989 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
990 return ScalarType->getOpcode() == TypeOpcode;
991 }
992 return false;
993}
994
995unsigned
998}
999
1000unsigned
1002 if (!Type)
1003 return 0;
1004 return Type->getOpcode() == SPIRV::OpTypeVector
1005 ? static_cast<unsigned>(Type->getOperand(2).getImm())
1006 : 1;
1007}
1008
1009unsigned
1011 assert(Type && "Invalid Type pointer");
1012 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1013 auto EleTypeReg = Type->getOperand(1).getReg();
1014 Type = getSPIRVTypeForVReg(EleTypeReg);
1015 }
1016 if (Type->getOpcode() == SPIRV::OpTypeInt ||
1017 Type->getOpcode() == SPIRV::OpTypeFloat)
1018 return Type->getOperand(1).getImm();
1019 if (Type->getOpcode() == SPIRV::OpTypeBool)
1020 return 1;
1021 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
1022}
1023
1025 const SPIRVType *Type) const {
1026 assert(Type && "Invalid Type pointer");
1027 unsigned NumElements = 1;
1028 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1029 NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1030 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1031 }
1032 return Type->getOpcode() == SPIRV::OpTypeInt ||
1033 Type->getOpcode() == SPIRV::OpTypeFloat
1034 ? NumElements * Type->getOperand(1).getImm()
1035 : 0;
1036}
1037
1039 const SPIRVType *Type) const {
1040 if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1041 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1042 return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1043}
1044
1047 return IntType && IntType->getOperand(2).getImm() != 0;
1048}
1049
1051 SPIRVType *PtrType = getSPIRVTypeForVReg(PtrReg);
1052 SPIRVType *ElemType =
1053 PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1054 ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1055 : nullptr;
1056 return ElemType ? ElemType->getOpcode() : 0;
1057}
1058
1060 const SPIRVType *Type2) const {
1061 if (!Type1 || !Type2)
1062 return false;
1063 auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1064 // Ignore difference between <1.5 and >=1.5 protocol versions:
1065 // it's valid if either Result Type or Operand is a pointer, and the other
1066 // is a pointer, an integer scalar, or an integer vector.
1067 if (Op1 == SPIRV::OpTypePointer &&
1068 (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1069 return true;
1070 if (Op2 == SPIRV::OpTypePointer &&
1071 (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1072 return true;
1073 unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1075 return Bits1 > 0 && Bits1 == Bits2;
1076}
1077
1078SPIRV::StorageClass::StorageClass
1081 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
1082 Type->getOperand(1).isImm() && "Pointer type is expected");
1083 return static_cast<SPIRV::StorageClass::StorageClass>(
1084 Type->getOperand(1).getImm());
1085}
1086
1088 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1089 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1090 SPIRV::ImageFormat::ImageFormat ImageFormat,
1091 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1092 SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
1093 Arrayed, Multisampled, Sampled, ImageFormat,
1094 AccessQual);
1095 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1096 return Res;
1097 Register ResVReg = createTypeVReg(MIRBuilder);
1098 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1099 return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1100 .addDef(ResVReg)
1101 .addUse(getSPIRVTypeID(SampledType))
1102 .addImm(Dim)
1103 .addImm(Depth) // Depth (whether or not it is a Depth image).
1104 .addImm(Arrayed) // Arrayed.
1105 .addImm(Multisampled) // Multisampled (0 = only single-sample).
1106 .addImm(Sampled) // Sampled (0 = usage known at runtime).
1107 .addImm(ImageFormat)
1108 .addImm(AccessQual);
1109}
1110
1111SPIRVType *
1114 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1115 return Res;
1116 Register ResVReg = createTypeVReg(MIRBuilder);
1117 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1118 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
1119}
1120
1122 MachineIRBuilder &MIRBuilder,
1123 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1124 SPIRV::PipeTypeDescriptor TD(AccessQual);
1125 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1126 return Res;
1127 Register ResVReg = createTypeVReg(MIRBuilder);
1128 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1129 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1130 .addDef(ResVReg)
1131 .addImm(AccessQual);
1132}
1133
1135 MachineIRBuilder &MIRBuilder) {
1137 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1138 return Res;
1139 Register ResVReg = createTypeVReg(MIRBuilder);
1140 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1141 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
1142}
1143
1145 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1147 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1148 ImageType->getOperand(1).getReg())),
1149 ImageType);
1150 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1151 return Res;
1152 Register ResVReg = createTypeVReg(MIRBuilder);
1153 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1154 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1155 .addDef(ResVReg)
1156 .addUse(getSPIRVTypeID(ImageType));
1157}
1158
1160 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1161 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
1162 if (ResVReg.isValid())
1163 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1164 ResVReg = createTypeVReg(MIRBuilder);
1165 SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
1166 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
1167 return SpirvTy;
1168}
1169
1170const MachineInstr *
1171SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
1172 MachineIRBuilder &MIRBuilder) {
1173 Register Reg = DT.find(TD, &MIRBuilder.getMF());
1174 if (Reg.isValid())
1175 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
1176 return nullptr;
1177}
1178
1179// Returns nullptr if unable to recognize SPIRV type name
1181 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
1182 SPIRV::StorageClass::StorageClass SC,
1183 SPIRV::AccessQualifier::AccessQualifier AQ) {
1184 unsigned VecElts = 0;
1185 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1186
1187 // Parse strings representing either a SPIR-V or OpenCL builtin type.
1188 if (hasBuiltinTypePrefix(TypeStr))
1190 TypeStr.str(), MIRBuilder.getContext()),
1191 MIRBuilder, AQ);
1192
1193 // Parse type name in either "typeN" or "type vector[N]" format, where
1194 // N is the number of elements of the vector.
1195 Type *Ty;
1196
1197 Ty = parseBasicTypeName(TypeStr, Ctx);
1198 if (!Ty)
1199 // Unable to recognize SPIRV type name
1200 return nullptr;
1201
1202 auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
1203
1204 // Handle "type*" or "type* vector[N]".
1205 if (TypeStr.starts_with("*")) {
1206 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1207 TypeStr = TypeStr.substr(strlen("*"));
1208 }
1209
1210 // Handle "typeN*" or "type vector[N]*".
1211 bool IsPtrToVec = TypeStr.consume_back("*");
1212
1213 if (TypeStr.consume_front(" vector[")) {
1214 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1215 }
1216 TypeStr.getAsInteger(10, VecElts);
1217 if (VecElts > 0)
1218 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
1219
1220 if (IsPtrToVec)
1221 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1222
1223 return SpirvTy;
1224}
1225
1226SPIRVType *
1228 MachineIRBuilder &MIRBuilder) {
1229 return getOrCreateSPIRVType(
1231 MIRBuilder);
1232}
1233
1234SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1235 SPIRVType *SpirvType) {
1236 assert(CurMF == SpirvType->getMF());
1237 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1238 SPIRVToLLVMType[SpirvType] = LLVMTy;
1239 return SpirvType;
1240}
1241
1243 MachineInstr &I,
1244 const SPIRVInstrInfo &TII,
1245 unsigned SPIRVOPcode,
1246 Type *LLVMTy) {
1247 Register Reg = DT.find(LLVMTy, CurMF);
1248 if (Reg.isValid())
1249 return getSPIRVTypeForVReg(Reg);
1250 MachineBasicBlock &BB = *I.getParent();
1251 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRVOPcode))
1254 .addImm(0);
1255 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1256 return finishCreatingSPIRVType(LLVMTy, MIB);
1257}
1258
1260 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1262 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1263}
1265 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1267 Type *LLVMTy;
1268 switch (BitWidth) {
1269 case 16:
1270 LLVMTy = Type::getHalfTy(Ctx);
1271 break;
1272 case 32:
1273 LLVMTy = Type::getFloatTy(Ctx);
1274 break;
1275 case 64:
1276 LLVMTy = Type::getDoubleTy(Ctx);
1277 break;
1278 default:
1279 llvm_unreachable("Bit width is of unexpected size.");
1280 }
1281 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1282}
1283
1284SPIRVType *
1286 return getOrCreateSPIRVType(
1287 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1288 MIRBuilder);
1289}
1290
1291SPIRVType *
1293 const SPIRVInstrInfo &TII) {
1295 Register Reg = DT.find(LLVMTy, CurMF);
1296 if (Reg.isValid())
1297 return getSPIRVTypeForVReg(Reg);
1298 MachineBasicBlock &BB = *I.getParent();
1299 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1301 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1302 return finishCreatingSPIRVType(LLVMTy, MIB);
1303}
1304
1306 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1307 return getOrCreateSPIRVType(
1309 NumElements),
1310 MIRBuilder);
1311}
1312
1314 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1315 const SPIRVInstrInfo &TII) {
1316 Type *LLVMTy = FixedVectorType::get(
1317 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1318 Register Reg = DT.find(LLVMTy, CurMF);
1319 if (Reg.isValid())
1320 return getSPIRVTypeForVReg(Reg);
1321 MachineBasicBlock &BB = *I.getParent();
1322 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1325 .addImm(NumElements);
1326 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1327 return finishCreatingSPIRVType(LLVMTy, MIB);
1328}
1329
1331 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1332 const SPIRVInstrInfo &TII) {
1333 Type *LLVMTy = ArrayType::get(
1334 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1335 Register Reg = DT.find(LLVMTy, CurMF);
1336 if (Reg.isValid())
1337 return getSPIRVTypeForVReg(Reg);
1338 MachineBasicBlock &BB = *I.getParent();
1339 SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1340 Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1341 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1344 .addUse(Len);
1345 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1346 return finishCreatingSPIRVType(LLVMTy, MIB);
1347}
1348
1350 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1351 SPIRV::StorageClass::StorageClass SC) {
1352 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1354 Type *LLVMTy = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1355 AddressSpace);
1356 // check if this type is already available
1357 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1358 if (Reg.isValid())
1359 return getSPIRVTypeForVReg(Reg);
1360 // create a new type
1361 auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1362 MIRBuilder.getDebugLoc(),
1363 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1365 .addImm(static_cast<uint32_t>(SC))
1367 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1368 return finishCreatingSPIRVType(LLVMTy, MIB);
1369}
1370
1373 SPIRV::StorageClass::StorageClass SC) {
1374 MachineIRBuilder MIRBuilder(I);
1375 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1376}
1377
1379 SPIRVType *SpvType,
1380 const SPIRVInstrInfo &TII) {
1381 assert(SpvType);
1382 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1383 assert(LLVMTy);
1384 // Find a constant in DT or build a new one.
1385 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1386 Register Res = DT.find(UV, CurMF);
1387 if (Res.isValid())
1388 return Res;
1389 LLT LLTy = LLT::scalar(32);
1391 CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1392 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1393 DT.add(UV, CurMF, Res);
1394
1396 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1397 .addDef(Res)
1398 .addUse(getSPIRVTypeID(SpvType));
1399 const auto &ST = CurMF->getSubtarget();
1400 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1401 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1402 return Res;
1403}
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:1810
const HexagonInstrInfo * TII
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Register createTypeVReg(MachineIRBuilder &MIRBuilder)
APInt bitcastToAPInt() const
Definition: APFloat.h:1210
bool isPosZero() const
Definition: APFloat.h:1306
Class for arbitrary precision integers.
Definition: APInt.h:76
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:647
Type * getElementType() const
Definition: DerivedTypes.h:384
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1291
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:268
const APFloat & getValueAPF() const
Definition: Constants.h:311
This is the shared class of boolean and integer constants.
Definition: Constants.h:80
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1775
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1449
This is an important base class in LLVM.
Definition: Constant.h:41
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:1758
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:692
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:356
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:655
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:51
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:278
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:1067
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:558
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:722
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:711
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:568
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.
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)
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 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 * 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 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:647
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:462
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:563
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:627
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:289
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:590
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:265
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:252
Type * getArrayElementType() const
Definition: Type.h:404
uint64_t getArrayNumElements() const
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:129
static IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:185
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:228
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
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:1348
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1808
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.
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)
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
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:379
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:156
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:190
Type * toTypedPointer(Type *Ty, LLVMContext &Ctx)
Definition: SPIRVUtils.h:156
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Definition: SPIRVUtils.cpp:400
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:191
bool hasBuiltinTypePrefix(StringRef Name)
Definition: SPIRVUtils.cpp:372
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