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#include <functional>
29
30using namespace llvm;
31
32inline unsigned typeToAddressSpace(const Type *Ty) {
33 if (auto PType = dyn_cast<TypedPointerType>(Ty))
34 return PType->getAddressSpace();
35 if (auto PType = dyn_cast<PointerType>(Ty))
36 return PType->getAddressSpace();
37 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
38 ExtTy && isTypedPointerWrapper(ExtTy))
39 return ExtTy->getIntParameter(0);
40 report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
41}
42
44 : PointerSize(PointerSize), Bound(0) {}
45
47 Register VReg,
49 const SPIRVInstrInfo &TII) {
51 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
52 return SpirvType;
53}
54
58 const SPIRVInstrInfo &TII) {
60 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
61 return SpirvType;
62}
63
65 SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
66 const SPIRVInstrInfo &TII) {
67 SPIRVType *SpirvType =
69 assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
70 return SpirvType;
71}
72
74 const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
75 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
76 SPIRVType *SpirvType =
77 getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
78 assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
79 return SpirvType;
80}
81
83 Register VReg,
84 const MachineFunction &MF) {
85 VRegToTypeMap[&MF][VReg] = SpirvType;
86}
87
89 auto Res = MRI.createGenericVirtualRegister(LLT::scalar(64));
90 MRI.setRegClass(Res, &SPIRV::TYPERegClass);
91 return Res;
92}
93
95 return createTypeVReg(MIRBuilder.getMF().getRegInfo());
96}
97
98SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
99 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
100 return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
101 .addDef(createTypeVReg(MIRBuilder));
102 });
103}
104
105unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
106 if (Width > 64)
107 report_fatal_error("Unsupported integer width!");
108 const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
109 if (ST.canUseExtension(
110 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers))
111 return Width;
112 if (Width <= 8)
113 Width = 8;
114 else if (Width <= 16)
115 Width = 16;
116 else if (Width <= 32)
117 Width = 32;
118 else
119 Width = 64;
120 return Width;
121}
122
123SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
124 MachineIRBuilder &MIRBuilder,
125 bool IsSigned) {
126 Width = adjustOpTypeIntWidth(Width);
127 const SPIRVSubtarget &ST =
128 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
129 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
130 if (ST.canUseExtension(
131 SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
132 MIRBuilder.buildInstr(SPIRV::OpExtension)
133 .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
134 MIRBuilder.buildInstr(SPIRV::OpCapability)
135 .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
136 }
137 return MIRBuilder.buildInstr(SPIRV::OpTypeInt)
138 .addDef(createTypeVReg(MIRBuilder))
139 .addImm(Width)
140 .addImm(IsSigned ? 1 : 0);
141 });
142}
143
144SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
145 MachineIRBuilder &MIRBuilder) {
146 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
147 return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
148 .addDef(createTypeVReg(MIRBuilder))
149 .addImm(Width);
150 });
151}
152
153SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
154 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
155 return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
156 .addDef(createTypeVReg(MIRBuilder));
157 });
158}
159
161 // TODO:
162 // - take into account duplicate tracker case which is a known issue,
163 // - review other data structure wrt. possible issues related to removal
164 // of a machine instruction during instruction selection.
165 const MachineFunction *MF = MI->getParent()->getParent();
166 auto It = LastInsertedTypeMap.find(MF);
167 if (It == LastInsertedTypeMap.end())
168 return;
169 if (It->second == MI)
170 LastInsertedTypeMap.erase(MF);
171}
172
173SPIRVType *SPIRVGlobalRegistry::createOpType(
174 MachineIRBuilder &MIRBuilder,
175 std::function<MachineInstr *(MachineIRBuilder &)> Op) {
176 auto oldInsertPoint = MIRBuilder.getInsertPt();
177 MachineBasicBlock *OldMBB = &MIRBuilder.getMBB();
178 MachineBasicBlock *NewMBB = &*MIRBuilder.getMF().begin();
179
180 auto LastInsertedType = LastInsertedTypeMap.find(CurMF);
181 if (LastInsertedType != LastInsertedTypeMap.end()) {
182 auto It = LastInsertedType->second->getIterator();
183 // It might happen that this instruction was removed from the first MBB,
184 // hence the Parent's check.
186 if (It->getParent() != NewMBB)
187 InsertAt = oldInsertPoint->getParent() == NewMBB
188 ? oldInsertPoint
189 : getInsertPtValidEnd(NewMBB);
190 else if (It->getNextNode())
191 InsertAt = It->getNextNode()->getIterator();
192 else
193 InsertAt = getInsertPtValidEnd(NewMBB);
194 MIRBuilder.setInsertPt(*NewMBB, InsertAt);
195 } else {
196 MIRBuilder.setInsertPt(*NewMBB, NewMBB->begin());
197 auto Result = LastInsertedTypeMap.try_emplace(CurMF, nullptr);
198 assert(Result.second);
199 LastInsertedType = Result.first;
200 }
201
202 MachineInstr *Type = Op(MIRBuilder);
203 // We expect all users of this function to insert definitions at the insertion
204 // point set above that is always the first MBB.
205 assert(Type->getParent() == NewMBB);
206 LastInsertedType->second = Type;
207
208 MIRBuilder.setInsertPt(*OldMBB, oldInsertPoint);
209 return Type;
210}
211
212SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
213 SPIRVType *ElemType,
214 MachineIRBuilder &MIRBuilder) {
215 auto EleOpc = ElemType->getOpcode();
216 (void)EleOpc;
217 assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
218 EleOpc == SPIRV::OpTypeBool) &&
219 "Invalid vector element type");
220
221 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
222 return MIRBuilder.buildInstr(SPIRV::OpTypeVector)
223 .addDef(createTypeVReg(MIRBuilder))
224 .addUse(getSPIRVTypeID(ElemType))
225 .addImm(NumElems);
226 });
227}
228
229std::tuple<Register, ConstantInt *, bool, unsigned>
230SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
231 MachineIRBuilder *MIRBuilder,
233 const SPIRVInstrInfo *TII) {
234 assert(SpvType);
235 const IntegerType *LLVMIntTy =
236 cast<IntegerType>(getTypeForSPIRVType(SpvType));
237 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
238 bool NewInstr = false;
239 // Find a constant in DT or build a new one.
240 ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
241 Register Res = DT.find(CI, CurMF);
242 if (!Res.isValid()) {
243 Res =
245 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
246 if (MIRBuilder)
247 assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
248 else
250 DT.add(CI, CurMF, Res);
251 NewInstr = true;
252 }
253 return std::make_tuple(Res, CI, NewInstr, BitWidth);
254}
255
256std::tuple<Register, ConstantFP *, bool, unsigned>
257SPIRVGlobalRegistry::getOrCreateConstFloatReg(APFloat Val, SPIRVType *SpvType,
258 MachineIRBuilder *MIRBuilder,
260 const SPIRVInstrInfo *TII) {
261 assert(SpvType);
263 const Type *LLVMFloatTy = getTypeForSPIRVType(SpvType);
264 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
265 bool NewInstr = false;
266 // Find a constant in DT or build a new one.
267 auto *const CI = ConstantFP::get(Ctx, Val);
268 Register Res = DT.find(CI, CurMF);
269 if (!Res.isValid()) {
270 Res =
272 CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
273 if (MIRBuilder)
274 assignTypeToVReg(LLVMFloatTy, Res, *MIRBuilder);
275 else
277 DT.add(CI, CurMF, Res);
278 NewInstr = true;
279 }
280 return std::make_tuple(Res, CI, NewInstr, BitWidth);
281}
282
284 SPIRVType *SpvType,
285 const SPIRVInstrInfo &TII,
286 bool ZeroAsNull) {
287 assert(SpvType);
288 ConstantFP *CI;
289 Register Res;
290 bool New;
291 unsigned BitWidth;
292 std::tie(Res, CI, New, BitWidth) =
293 getOrCreateConstFloatReg(Val, SpvType, nullptr, &I, &TII);
294 // If we have found Res register which is defined by the passed G_CONSTANT
295 // machine instruction, a new constant instruction should be created.
296 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
297 return Res;
298 MachineIRBuilder MIRBuilder(I);
299 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
301 // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
302 if (Val.isPosZero() && ZeroAsNull) {
303 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
304 .addDef(Res)
305 .addUse(getSPIRVTypeID(SpvType));
306 } else {
307 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
308 .addDef(Res)
309 .addUse(getSPIRVTypeID(SpvType));
310 addNumImm(
311 APInt(BitWidth, CI->getValueAPF().bitcastToAPInt().getZExtValue()),
312 MIB);
313 }
314 const auto &ST = CurMF->getSubtarget();
316 *MIB, *ST.getInstrInfo(), *ST.getRegisterInfo(), *ST.getRegBankInfo());
317 return MIB;
318 });
319 return Res;
320}
321
323 SPIRVType *SpvType,
324 const SPIRVInstrInfo &TII,
325 bool ZeroAsNull) {
326 assert(SpvType);
327 ConstantInt *CI;
328 Register Res;
329 bool New;
330 unsigned BitWidth;
331 std::tie(Res, CI, New, BitWidth) =
332 getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
333 // If we have found Res register which is defined by the passed G_CONSTANT
334 // machine instruction, a new constant instruction should be created.
335 if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
336 return Res;
337
338 MachineIRBuilder MIRBuilder(I);
339 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
341 if (Val || !ZeroAsNull) {
342 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
343 .addDef(Res)
344 .addUse(getSPIRVTypeID(SpvType));
345 addNumImm(APInt(BitWidth, Val), MIB);
346 } else {
347 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
348 .addDef(Res)
349 .addUse(getSPIRVTypeID(SpvType));
350 }
351 const auto &ST = CurMF->getSubtarget();
353 *MIB, *ST.getInstrInfo(), *ST.getRegisterInfo(), *ST.getRegBankInfo());
354 return MIB;
355 });
356 return Res;
357}
358
360 MachineIRBuilder &MIRBuilder,
361 SPIRVType *SpvType, bool EmitIR,
362 bool ZeroAsNull) {
363 assert(SpvType);
364 auto &MF = MIRBuilder.getMF();
365 const IntegerType *LLVMIntTy =
366 cast<IntegerType>(getTypeForSPIRVType(SpvType));
367 // Find a constant in DT or build a new one.
368 const auto ConstInt =
369 ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
370 Register Res = DT.find(ConstInt, &MF);
371 if (!Res.isValid()) {
372 unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);
373 LLT LLTy = LLT::scalar(BitWidth);
374 Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
375 MF.getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
376 assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
377 SPIRV::AccessQualifier::ReadWrite, EmitIR);
378 DT.add(ConstInt, &MIRBuilder.getMF(), Res);
379 if (EmitIR) {
380 MIRBuilder.buildConstant(Res, *ConstInt);
381 } else {
382 Register SpvTypeReg = getSPIRVTypeID(SpvType);
383 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
385 if (Val || !ZeroAsNull) {
386 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
387 .addDef(Res)
388 .addUse(SpvTypeReg);
389 addNumImm(APInt(BitWidth, Val), MIB);
390 } else {
391 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
392 .addDef(Res)
393 .addUse(SpvTypeReg);
394 }
395 const auto &Subtarget = CurMF->getSubtarget();
396 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
397 *Subtarget.getRegisterInfo(),
398 *Subtarget.getRegBankInfo());
399 return MIB;
400 });
401 }
402 }
403 return Res;
404}
405
407 MachineIRBuilder &MIRBuilder,
408 SPIRVType *SpvType) {
409 auto &MF = MIRBuilder.getMF();
410 auto &Ctx = MF.getFunction().getContext();
411 if (!SpvType) {
412 const Type *LLVMFPTy = Type::getFloatTy(Ctx);
413 SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
414 }
415 // Find a constant in DT or build a new one.
416 const auto ConstFP = ConstantFP::get(Ctx, Val);
417 Register Res = DT.find(ConstFP, &MF);
418 if (!Res.isValid()) {
419 Res = MF.getRegInfo().createGenericVirtualRegister(
421 MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);
422 assignSPIRVTypeToVReg(SpvType, Res, MF);
423 DT.add(ConstFP, &MF, Res);
424 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
426 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
427 .addDef(Res)
428 .addUse(getSPIRVTypeID(SpvType));
429 addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
430 return MIB;
431 });
432 }
433
434 return Res;
435}
436
437Register SPIRVGlobalRegistry::getOrCreateBaseRegister(
438 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
439 const SPIRVInstrInfo &TII, unsigned BitWidth, bool ZeroAsNull) {
440 SPIRVType *Type = SpvType;
441 if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
442 SpvType->getOpcode() == SPIRV::OpTypeArray) {
443 auto EleTypeReg = SpvType->getOperand(1).getReg();
444 Type = getSPIRVTypeForVReg(EleTypeReg);
445 }
446 if (Type->getOpcode() == SPIRV::OpTypeFloat) {
448 return getOrCreateConstFP(dyn_cast<ConstantFP>(Val)->getValue(), I,
449 SpvBaseType, TII, ZeroAsNull);
450 }
451 assert(Type->getOpcode() == SPIRV::OpTypeInt);
454 SpvBaseType, TII, ZeroAsNull);
455}
456
457Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
458 Constant *Val, MachineInstr &I, SPIRVType *SpvType,
459 const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
460 unsigned ElemCnt, bool ZeroAsNull) {
461 // Find a constant vector or array in DT or build a new one.
462 Register Res = DT.find(CA, CurMF);
463 // If no values are attached, the composite is null constant.
464 bool IsNull = Val->isNullValue() && ZeroAsNull;
465 if (!Res.isValid()) {
466 // SpvScalConst should be created before SpvVecConst to avoid undefined ID
467 // error on validation.
468 // TODO: can moved below once sorting of types/consts/defs is implemented.
469 Register SpvScalConst;
470 if (!IsNull)
471 SpvScalConst =
472 getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);
473
474 LLT LLTy = LLT::scalar(64);
475 Register SpvVecConst =
477 CurMF->getRegInfo().setRegClass(SpvVecConst, getRegClass(SpvType));
478 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
479 DT.add(CA, CurMF, SpvVecConst);
480 MachineIRBuilder MIRBuilder(I);
481 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
483 if (!IsNull) {
484 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
485 .addDef(SpvVecConst)
486 .addUse(getSPIRVTypeID(SpvType));
487 for (unsigned i = 0; i < ElemCnt; ++i)
488 MIB.addUse(SpvScalConst);
489 } else {
490 MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
491 .addDef(SpvVecConst)
492 .addUse(getSPIRVTypeID(SpvType));
493 }
494 const auto &Subtarget = CurMF->getSubtarget();
495 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
496 *Subtarget.getRegisterInfo(),
497 *Subtarget.getRegBankInfo());
498 return MIB;
499 });
500 return SpvVecConst;
501 }
502 return Res;
503}
504
507 SPIRVType *SpvType,
508 const SPIRVInstrInfo &TII,
509 bool ZeroAsNull) {
510 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
511 assert(LLVMTy->isVectorTy());
512 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
513 Type *LLVMBaseTy = LLVMVecTy->getElementType();
514 assert(LLVMBaseTy->isIntegerTy());
515 auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
516 auto *ConstVec =
517 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
518 unsigned BW = getScalarOrVectorBitWidth(SpvType);
519 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
520 SpvType->getOperand(2).getImm(),
521 ZeroAsNull);
522}
523
526 SPIRVType *SpvType,
527 const SPIRVInstrInfo &TII,
528 bool ZeroAsNull) {
529 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
530 assert(LLVMTy->isVectorTy());
531 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
532 Type *LLVMBaseTy = LLVMVecTy->getElementType();
533 assert(LLVMBaseTy->isFloatingPointTy());
534 auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
535 auto *ConstVec =
536 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
537 unsigned BW = getScalarOrVectorBitWidth(SpvType);
538 return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
539 SpvType->getOperand(2).getImm(),
540 ZeroAsNull);
541}
542
544 uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,
545 const SPIRVInstrInfo &TII) {
546 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
547 assert(LLVMTy->isArrayTy());
548 const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
549 Type *LLVMBaseTy = LLVMArrTy->getElementType();
550 Constant *CI = ConstantInt::get(LLVMBaseTy, Val);
551 SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
552 unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
553 // The following is reasonably unique key that is better that [Val]. The naive
554 // alternative would be something along the lines of:
555 // SmallVector<Constant *> NumCI(Num, CI);
556 // Constant *UniqueKey =
557 // ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);
558 // that would be a truly unique but dangerous key, because it could lead to
559 // the creation of constants of arbitrary length (that is, the parameter of
560 // memset) which were missing in the original module.
562 {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),
563 ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});
564 return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,
565 LLVMArrTy->getNumElements());
566}
567
568Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
569 uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
570 Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
571 Register Res = DT.find(CA, CurMF);
572 if (!Res.isValid()) {
573 Register SpvScalConst;
574 if (Val || EmitIR) {
575 SPIRVType *SpvBaseType =
577 SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
578 }
579 LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);
580 Register SpvVecConst =
582 CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::iIDRegClass);
583 assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
584 DT.add(CA, CurMF, SpvVecConst);
585 if (EmitIR) {
586 MIRBuilder.buildSplatBuildVector(SpvVecConst, SpvScalConst);
587 } else {
588 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
589 if (Val) {
590 auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
591 .addDef(SpvVecConst)
592 .addUse(getSPIRVTypeID(SpvType));
593 for (unsigned i = 0; i < ElemCnt; ++i)
594 MIB.addUse(SpvScalConst);
595 return MIB;
596 } else {
597 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
598 .addDef(SpvVecConst)
599 .addUse(getSPIRVTypeID(SpvType));
600 }
601 });
602 }
603 return SpvVecConst;
604 }
605 return Res;
606}
607
610 MachineIRBuilder &MIRBuilder,
611 SPIRVType *SpvType, bool EmitIR) {
612 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
613 assert(LLVMTy->isVectorTy());
614 const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
615 Type *LLVMBaseTy = LLVMVecTy->getElementType();
616 const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
617 auto ConstVec =
618 ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
619 unsigned BW = getScalarOrVectorBitWidth(SpvType);
620 return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
621 ConstVec, BW,
622 SpvType->getOperand(2).getImm());
623}
624
627 SPIRVType *SpvType) {
628 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
629 unsigned AddressSpace = typeToAddressSpace(LLVMTy);
630 // Find a constant in DT or build a new one.
633 Register Res = DT.find(CP, CurMF);
634 if (!Res.isValid()) {
635 LLT LLTy = LLT::pointer(AddressSpace, PointerSize);
637 CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);
638 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
639 createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
640 return MIRBuilder.buildInstr(SPIRV::OpConstantNull)
641 .addDef(Res)
642 .addUse(getSPIRVTypeID(SpvType));
643 });
644 DT.add(CP, CurMF, Res);
645 }
646 return Res;
647}
648
650 Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
651 MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
652 SPIRVType *SampTy;
653 if (SpvType)
654 SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
655 else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t",
656 MIRBuilder)) == nullptr)
657 report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
658
659 auto Sampler =
660 ResReg.isValid()
661 ? ResReg
662 : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
663 auto Res = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
664 return MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
665 .addDef(Sampler)
666 .addUse(getSPIRVTypeID(SampTy))
667 .addImm(AddrMode)
668 .addImm(Param)
669 .addImm(FilerMode);
670 });
671 assert(Res->getOperand(0).isReg());
672 return Res->getOperand(0).getReg();
673}
674
677 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
678 const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
679 SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
680 bool IsInstSelector) {
681 const GlobalVariable *GVar = nullptr;
682 if (GV)
683 GVar = cast<const GlobalVariable>(GV);
684 else {
685 // If GV is not passed explicitly, use the name to find or construct
686 // the global variable.
687 Module *M = MIRBuilder.getMF().getFunction().getParent();
688 GVar = M->getGlobalVariable(Name);
689 if (GVar == nullptr) {
690 const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
691 // Module takes ownership of the global var.
692 GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
694 Twine(Name));
695 }
696 GV = GVar;
697 }
698 Register Reg = DT.find(GVar, &MIRBuilder.getMF());
699 if (Reg.isValid()) {
700 if (Reg != ResVReg)
701 MIRBuilder.buildCopy(ResVReg, Reg);
702 return ResVReg;
703 }
704
705 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
706 .addDef(ResVReg)
708 .addImm(static_cast<uint32_t>(Storage));
709
710 if (Init != 0) {
711 MIB.addUse(Init->getOperand(0).getReg());
712 }
713
714 // ISel may introduce a new register on this step, so we need to add it to
715 // DT and correct its type avoiding fails on the next stage.
716 if (IsInstSelector) {
717 const auto &Subtarget = CurMF->getSubtarget();
718 constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
719 *Subtarget.getRegisterInfo(),
720 *Subtarget.getRegBankInfo());
721 }
722 Reg = MIB->getOperand(0).getReg();
723 DT.add(GVar, &MIRBuilder.getMF(), Reg);
724 addGlobalObject(GVar, &MIRBuilder.getMF(), Reg);
725
726 // Set to Reg the same type as ResVReg has.
727 auto MRI = MIRBuilder.getMRI();
728 if (Reg != ResVReg) {
729 LLT RegLLTy =
730 LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
731 MRI->setType(Reg, RegLLTy);
732 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
733 } else {
734 // Our knowledge about the type may be updated.
735 // If that's the case, we need to update a type
736 // associated with the register.
737 SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
738 if (!DefType || DefType != BaseType)
739 assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
740 }
741
742 // If it's a global variable with name, output OpName for it.
743 if (GVar && GVar->hasName())
744 buildOpName(Reg, GVar->getName(), MIRBuilder);
745
746 // Output decorations for the GV.
747 // TODO: maybe move to GenerateDecorations pass.
748 const SPIRVSubtarget &ST =
749 cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
750 if (IsConst && ST.isOpenCLEnv())
751 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
752
753 if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
754 unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
755 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
756 }
757
758 if (HasLinkageTy)
759 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
760 {static_cast<uint32_t>(LinkageType)}, Name);
761
762 SPIRV::BuiltIn::BuiltIn BuiltInId;
763 if (getSpirvBuiltInIdByName(Name, BuiltInId))
764 buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
765 {static_cast<uint32_t>(BuiltInId)});
766
767 // If it's a global variable with "spirv.Decorations" metadata node
768 // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
769 // arguments.
770 MDNode *GVarMD = nullptr;
771 if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
772 buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD);
773
774 return Reg;
775}
776
777static std::string GetSpirvImageTypeName(const SPIRVType *Type,
778 MachineIRBuilder &MIRBuilder,
779 const std::string &Prefix);
780
781static std::string buildSpirvTypeName(const SPIRVType *Type,
782 MachineIRBuilder &MIRBuilder) {
783 switch (Type->getOpcode()) {
784 case SPIRV::OpTypeSampledImage: {
785 return GetSpirvImageTypeName(Type, MIRBuilder, "sampled_image_");
786 }
787 case SPIRV::OpTypeImage: {
788 return GetSpirvImageTypeName(Type, MIRBuilder, "image_");
789 }
790 case SPIRV::OpTypeArray: {
791 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
792 Register ElementTypeReg = Type->getOperand(1).getReg();
793 auto *ElementType = MRI->getUniqueVRegDef(ElementTypeReg);
794 const SPIRVType *TypeInst = MRI->getVRegDef(Type->getOperand(2).getReg());
795 assert(TypeInst->getOpcode() != SPIRV::OpConstantI);
796 MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg());
797 assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT);
798 uint32_t ArraySize = ImmInst->getOperand(1).getCImm()->getZExtValue();
799 return (buildSpirvTypeName(ElementType, MIRBuilder) + Twine("[") +
800 Twine(ArraySize) + Twine("]"))
801 .str();
802 }
803 case SPIRV::OpTypeFloat:
804 return ("f" + Twine(Type->getOperand(1).getImm())).str();
805 case SPIRV::OpTypeSampler:
806 return ("sampler");
807 case SPIRV::OpTypeInt:
808 if (Type->getOperand(2).getImm())
809 return ("i" + Twine(Type->getOperand(1).getImm())).str();
810 return ("u" + Twine(Type->getOperand(1).getImm())).str();
811 default:
812 llvm_unreachable("Trying to the the name of an unknown type.");
813 }
814}
815
816static std::string GetSpirvImageTypeName(const SPIRVType *Type,
817 MachineIRBuilder &MIRBuilder,
818 const std::string &Prefix) {
819 Register SampledTypeReg = Type->getOperand(1).getReg();
820 auto *SampledType = MIRBuilder.getMRI()->getUniqueVRegDef(SampledTypeReg);
821 std::string TypeName = Prefix + buildSpirvTypeName(SampledType, MIRBuilder);
822 for (uint32_t I = 2; I < Type->getNumOperands(); ++I) {
823 TypeName = (TypeName + '_' + Twine(Type->getOperand(I).getImm())).str();
824 }
825 return TypeName;
826}
827
829 const SPIRVType *VarType, uint32_t Set, uint32_t Binding,
830 MachineIRBuilder &MIRBuilder) {
831 SPIRVType *VarPointerTypeReg = getOrCreateSPIRVPointerType(
832 VarType, MIRBuilder, SPIRV::StorageClass::UniformConstant);
833 Register VarReg =
834 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
835
836 // TODO: The name should come from the llvm-ir, but how that name will be
837 // passed from the HLSL to the backend has not been decided. Using this place
838 // holder for now.
839 std::string Name = ("__resource_" + buildSpirvTypeName(VarType, MIRBuilder) +
840 "_" + Twine(Set) + "_" + Twine(Binding))
841 .str();
842 buildGlobalVariable(VarReg, VarPointerTypeReg, Name, nullptr,
843 SPIRV::StorageClass::UniformConstant, nullptr, false,
844 false, SPIRV::LinkageType::Import, MIRBuilder, false);
845
846 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::DescriptorSet, {Set});
847 buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::Binding, {Binding});
848 return VarReg;
849}
850
851SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
852 SPIRVType *ElemType,
853 MachineIRBuilder &MIRBuilder,
854 bool EmitIR) {
855 assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
856 "Invalid array element type");
857 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
858 Register NumElementsVReg =
859 buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);
860 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
861 return MIRBuilder.buildInstr(SPIRV::OpTypeArray)
862 .addDef(createTypeVReg(MIRBuilder))
863 .addUse(getSPIRVTypeID(ElemType))
864 .addUse(NumElementsVReg);
865 });
866}
867
868SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
869 MachineIRBuilder &MIRBuilder) {
870 assert(Ty->hasName());
871 const StringRef Name = Ty->hasName() ? Ty->getName() : "";
872 Register ResVReg = createTypeVReg(MIRBuilder);
873 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
874 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
875 addStringImm(Name, MIB);
876 buildOpName(ResVReg, Name, MIRBuilder);
877 return MIB;
878 });
879}
880
881SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
882 MachineIRBuilder &MIRBuilder,
883 bool EmitIR) {
884 SmallVector<Register, 4> FieldTypes;
885 for (const auto &Elem : Ty->elements()) {
886 SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder);
887 assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
888 "Invalid struct element type");
889 FieldTypes.push_back(getSPIRVTypeID(ElemTy));
890 }
891 Register ResVReg = createTypeVReg(MIRBuilder);
892 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
893 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
894 for (const auto &Ty : FieldTypes)
895 MIB.addUse(Ty);
896 if (Ty->hasName())
897 buildOpName(ResVReg, Ty->getName(), MIRBuilder);
898 if (Ty->isPacked())
899 buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
900 return MIB;
901 });
902}
903
904SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
905 const Type *Ty, MachineIRBuilder &MIRBuilder,
906 SPIRV::AccessQualifier::AccessQualifier AccQual) {
907 assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
908 return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
909}
910
911SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
912 SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
913 MachineIRBuilder &MIRBuilder, Register Reg) {
914 if (!Reg.isValid())
915 Reg = createTypeVReg(MIRBuilder);
916
917 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
918 return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
919 .addDef(Reg)
920 .addImm(static_cast<uint32_t>(SC))
921 .addUse(getSPIRVTypeID(ElemType));
922 });
923}
924
925SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
926 SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
927 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
928 return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
929 .addUse(createTypeVReg(MIRBuilder))
930 .addImm(static_cast<uint32_t>(SC));
931 });
932}
933
934SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
935 SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
936 MachineIRBuilder &MIRBuilder) {
937 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
938 .addDef(createTypeVReg(MIRBuilder))
939 .addUse(getSPIRVTypeID(RetType));
940 for (const SPIRVType *ArgType : ArgTypes)
941 MIB.addUse(getSPIRVTypeID(ArgType));
942 return MIB;
943}
944
946 const Type *Ty, SPIRVType *RetType,
947 const SmallVectorImpl<SPIRVType *> &ArgTypes,
948 MachineIRBuilder &MIRBuilder) {
949 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
950 if (Reg.isValid())
951 return getSPIRVTypeForVReg(Reg);
952 SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
953 DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
954 return finishCreatingSPIRVType(Ty, SpirvType);
955}
956
957SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
958 const Type *Ty, MachineIRBuilder &MIRBuilder,
959 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
960 Ty = adjustIntTypeByWidth(Ty);
961 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
962 if (Reg.isValid())
963 return getSPIRVTypeForVReg(Reg);
964 if (ForwardPointerTypes.contains(Ty))
965 return ForwardPointerTypes[Ty];
966 return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
967}
968
970 assert(SpirvType && "Attempting to get type id for nullptr type.");
971 if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
972 return SpirvType->uses().begin()->getReg();
973 return SpirvType->defs().begin()->getReg();
974}
975
976// We need to use a new LLVM integer type if there is a mismatch between
977// number of bits in LLVM and SPIRV integer types to let DuplicateTracker
978// ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without
979// such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the
980// same "OpTypeInt 8" type for a series of LLVM integer types with number of
981// bits less than 8. This would lead to duplicate type definitions
982// eventually due to the method that DuplicateTracker utilizes to reason
983// about uniqueness of type records.
984const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {
985 if (auto IType = dyn_cast<IntegerType>(Ty)) {
986 unsigned SrcBitWidth = IType->getBitWidth();
987 if (SrcBitWidth > 1) {
988 unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);
989 // Maybe change source LLVM type to keep DuplicateTracker consistent.
990 if (SrcBitWidth != BitWidth)
992 }
993 }
994 return Ty;
995}
996
997SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
998 const Type *Ty, MachineIRBuilder &MIRBuilder,
999 SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
1000 if (isSpecialOpaqueType(Ty))
1001 return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
1002 auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
1003 auto t = TypeToSPIRVTypeMap.find(Ty);
1004 if (t != TypeToSPIRVTypeMap.end()) {
1005 auto tt = t->second.find(&MIRBuilder.getMF());
1006 if (tt != t->second.end())
1007 return getSPIRVTypeForVReg(tt->second);
1008 }
1009
1010 if (auto IType = dyn_cast<IntegerType>(Ty)) {
1011 const unsigned Width = IType->getBitWidth();
1012 return Width == 1 ? getOpTypeBool(MIRBuilder)
1013 : getOpTypeInt(Width, MIRBuilder, false);
1014 }
1015 if (Ty->isFloatingPointTy())
1016 return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
1017 if (Ty->isVoidTy())
1018 return getOpTypeVoid(MIRBuilder);
1019 if (Ty->isVectorTy()) {
1020 SPIRVType *El =
1021 findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
1022 return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
1023 MIRBuilder);
1024 }
1025 if (Ty->isArrayTy()) {
1026 SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
1027 return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
1028 }
1029 if (auto SType = dyn_cast<StructType>(Ty)) {
1030 if (SType->isOpaque())
1031 return getOpTypeOpaque(SType, MIRBuilder);
1032 return getOpTypeStruct(SType, MIRBuilder, EmitIR);
1033 }
1034 if (auto FType = dyn_cast<FunctionType>(Ty)) {
1035 SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
1036 SmallVector<SPIRVType *, 4> ParamTypes;
1037 for (const auto &t : FType->params()) {
1038 ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
1039 }
1040 return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
1041 }
1042
1043 unsigned AddrSpace = typeToAddressSpace(Ty);
1044 SPIRVType *SpvElementType = nullptr;
1045 if (Type *ElemTy = ::getPointeeType(Ty))
1046 SpvElementType = getOrCreateSPIRVType(ElemTy, MIRBuilder, AccQual, EmitIR);
1047 else
1048 SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
1049
1050 // Get access to information about available extensions
1051 const SPIRVSubtarget *ST =
1052 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
1053 auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
1054 // Null pointer means we have a loop in type definitions, make and
1055 // return corresponding OpTypeForwardPointer.
1056 if (SpvElementType == nullptr) {
1057 if (!ForwardPointerTypes.contains(Ty))
1058 ForwardPointerTypes[Ty] = getOpTypeForwardPointer(SC, MIRBuilder);
1059 return ForwardPointerTypes[Ty];
1060 }
1061 // If we have forward pointer associated with this type, use its register
1062 // operand to create OpTypePointer.
1063 if (ForwardPointerTypes.contains(Ty)) {
1064 Register Reg = getSPIRVTypeID(ForwardPointerTypes[Ty]);
1065 return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
1066 }
1067
1068 return getOrCreateSPIRVPointerType(SpvElementType, MIRBuilder, SC);
1069}
1070
1071SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
1072 const Type *Ty, MachineIRBuilder &MIRBuilder,
1073 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
1074 if (TypesInProcessing.count(Ty) && !isPointerTyOrWrapper(Ty))
1075 return nullptr;
1076 TypesInProcessing.insert(Ty);
1077 SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
1078 TypesInProcessing.erase(Ty);
1079 VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
1080 SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
1081 Register Reg = DT.find(Ty, &MIRBuilder.getMF());
1082 // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
1083 // will be added later. For special types it is already added to DT.
1084 if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
1085 !isSpecialOpaqueType(Ty)) {
1086 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1087 ExtTy && isTypedPointerWrapper(ExtTy))
1088 DT.add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0),
1089 &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
1090 else if (!isPointerTy(Ty))
1091 DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
1092 else if (isTypedPointerTy(Ty))
1093 DT.add(cast<TypedPointerType>(Ty)->getElementType(),
1094 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
1095 getSPIRVTypeID(SpirvType));
1096 else
1097 DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
1098 getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
1099 getSPIRVTypeID(SpirvType));
1100 }
1101
1102 return SpirvType;
1103}
1104
1105SPIRVType *
1107 const MachineFunction *MF) const {
1108 auto t = VRegToTypeMap.find(MF ? MF : CurMF);
1109 if (t != VRegToTypeMap.end()) {
1110 auto tt = t->second.find(VReg);
1111 if (tt != t->second.end())
1112 return tt->second;
1113 }
1114 return nullptr;
1115}
1116
1118 MachineInstr *Instr = getVRegDef(CurMF->getRegInfo(), VReg);
1119 return getSPIRVTypeForVReg(Instr->getOperand(1).getReg());
1120}
1121
1123 const Type *Ty, MachineIRBuilder &MIRBuilder,
1124 SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
1125 Register Reg;
1126 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
1127 ExtTy && isTypedPointerWrapper(ExtTy)) {
1128 Reg = DT.find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0),
1129 &MIRBuilder.getMF());
1130 } else if (!isPointerTy(Ty)) {
1131 Ty = adjustIntTypeByWidth(Ty);
1132 Reg = DT.find(Ty, &MIRBuilder.getMF());
1133 } else if (isTypedPointerTy(Ty)) {
1134 Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(),
1135 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
1136 } else {
1137 Reg =
1138 DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
1139 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
1140 }
1141
1142 if (Reg.isValid() && !isSpecialOpaqueType(Ty))
1143 return getSPIRVTypeForVReg(Reg);
1144 TypesInProcessing.clear();
1145 SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
1146 // Create normal pointer types for the corresponding OpTypeForwardPointers.
1147 for (auto &CU : ForwardPointerTypes) {
1148 const Type *Ty2 = CU.first;
1149 SPIRVType *STy2 = CU.second;
1150 if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
1151 STy2 = getSPIRVTypeForVReg(Reg);
1152 else
1153 STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
1154 if (Ty == Ty2)
1155 STy = STy2;
1156 }
1157 ForwardPointerTypes.clear();
1158 return STy;
1159}
1160
1162 unsigned TypeOpcode) const {
1164 assert(Type && "isScalarOfType VReg has no type assigned");
1165 return Type->getOpcode() == TypeOpcode;
1166}
1167
1169 unsigned TypeOpcode) const {
1171 assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
1172 if (Type->getOpcode() == TypeOpcode)
1173 return true;
1174 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1175 Register ScalarTypeVReg = Type->getOperand(1).getReg();
1176 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
1177 return ScalarType->getOpcode() == TypeOpcode;
1178 }
1179 return false;
1180}
1181
1182unsigned
1185}
1186
1187unsigned
1189 if (!Type)
1190 return 0;
1191 return Type->getOpcode() == SPIRV::OpTypeVector
1192 ? static_cast<unsigned>(Type->getOperand(2).getImm())
1193 : 1;
1194}
1195
1196SPIRVType *
1199}
1200
1201SPIRVType *
1203 if (!Type)
1204 return nullptr;
1205 Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector
1206 ? Type->getOperand(1).getReg()
1207 : Type->getOperand(0).getReg();
1208 SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);
1209 assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),
1210 ScalarType->getOpcode()));
1211 return ScalarType;
1212}
1213
1214unsigned
1216 assert(Type && "Invalid Type pointer");
1217 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1218 auto EleTypeReg = Type->getOperand(1).getReg();
1219 Type = getSPIRVTypeForVReg(EleTypeReg);
1220 }
1221 if (Type->getOpcode() == SPIRV::OpTypeInt ||
1222 Type->getOpcode() == SPIRV::OpTypeFloat)
1223 return Type->getOperand(1).getImm();
1224 if (Type->getOpcode() == SPIRV::OpTypeBool)
1225 return 1;
1226 llvm_unreachable("Attempting to get bit width of non-integer/float type.");
1227}
1228
1230 const SPIRVType *Type) const {
1231 assert(Type && "Invalid Type pointer");
1232 unsigned NumElements = 1;
1233 if (Type->getOpcode() == SPIRV::OpTypeVector) {
1234 NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1235 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1236 }
1237 return Type->getOpcode() == SPIRV::OpTypeInt ||
1238 Type->getOpcode() == SPIRV::OpTypeFloat
1239 ? NumElements * Type->getOperand(1).getImm()
1240 : 0;
1241}
1242
1244 const SPIRVType *Type) const {
1245 if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1246 Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1247 return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1248}
1249
1252 return IntType && IntType->getOperand(2).getImm() != 0;
1253}
1254
1256 return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1257 ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1258 : nullptr;
1259}
1260
1262 SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));
1263 return ElemType ? ElemType->getOpcode() : 0;
1264}
1265
1267 const SPIRVType *Type2) const {
1268 if (!Type1 || !Type2)
1269 return false;
1270 auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1271 // Ignore difference between <1.5 and >=1.5 protocol versions:
1272 // it's valid if either Result Type or Operand is a pointer, and the other
1273 // is a pointer, an integer scalar, or an integer vector.
1274 if (Op1 == SPIRV::OpTypePointer &&
1275 (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1276 return true;
1277 if (Op2 == SPIRV::OpTypePointer &&
1278 (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1279 return true;
1280 unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1282 return Bits1 > 0 && Bits1 == Bits2;
1283}
1284
1285SPIRV::StorageClass::StorageClass
1288 assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
1289 Type->getOperand(1).isImm() && "Pointer type is expected");
1291}
1292
1293SPIRV::StorageClass::StorageClass
1295 return static_cast<SPIRV::StorageClass::StorageClass>(
1296 Type->getOperand(1).getImm());
1297}
1298
1300 MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1301 uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1302 SPIRV::ImageFormat::ImageFormat ImageFormat,
1303 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1304 auto TD = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
1305 Depth, Arrayed, Multisampled, Sampled,
1306 ImageFormat, AccessQual);
1307 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1308 return Res;
1309 Register ResVReg = createTypeVReg(MIRBuilder);
1310 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1311 auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1312 .addDef(ResVReg)
1313 .addUse(getSPIRVTypeID(SampledType))
1314 .addImm(Dim)
1315 .addImm(Depth) // Depth (whether or not it is a Depth image).
1316 .addImm(Arrayed) // Arrayed.
1317 .addImm(Multisampled) // Multisampled (0 = only single-sample).
1318 .addImm(Sampled) // Sampled (0 = usage known at runtime).
1319 .addImm(ImageFormat);
1320
1321 if (AccessQual != SPIRV::AccessQualifier::None)
1322 MIB.addImm(AccessQual);
1323 return MIB;
1324}
1325
1326SPIRVType *
1328 auto TD = SPIRV::make_descr_sampler();
1329 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1330 return Res;
1331 Register ResVReg = createTypeVReg(MIRBuilder);
1332 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1333 return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
1334}
1335
1337 MachineIRBuilder &MIRBuilder,
1338 SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1339 auto TD = SPIRV::make_descr_pipe(AccessQual);
1340 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1341 return Res;
1342 Register ResVReg = createTypeVReg(MIRBuilder);
1343 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1344 return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1345 .addDef(ResVReg)
1346 .addImm(AccessQual);
1347}
1348
1350 MachineIRBuilder &MIRBuilder) {
1351 auto TD = SPIRV::make_descr_event();
1352 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1353 return Res;
1354 Register ResVReg = createTypeVReg(MIRBuilder);
1355 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1356 return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
1357}
1358
1360 SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1362 SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1363 ImageType->getOperand(1).getReg())),
1364 ImageType);
1365 if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1366 return Res;
1367 Register ResVReg = createTypeVReg(MIRBuilder);
1368 DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1369 return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1370 .addDef(ResVReg)
1371 .addUse(getSPIRVTypeID(ImageType));
1372}
1373
1375 MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
1376 const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
1377 uint32_t Use) {
1378 Register ResVReg = DT.find(ExtensionType, &MIRBuilder.getMF());
1379 if (ResVReg.isValid())
1380 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1381 ResVReg = createTypeVReg(MIRBuilder);
1382 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
1383 SPIRVType *SpirvTy =
1384 MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
1385 .addDef(ResVReg)
1386 .addUse(getSPIRVTypeID(ElemType))
1387 .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, true))
1388 .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, true))
1389 .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, true))
1390 .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, true));
1391 DT.add(ExtensionType, &MIRBuilder.getMF(), ResVReg);
1392 return SpirvTy;
1393}
1394
1396 const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1397 Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
1398 if (ResVReg.isValid())
1399 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1400 ResVReg = createTypeVReg(MIRBuilder);
1401 SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
1402 DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
1403 return SpirvTy;
1404}
1405
1406const MachineInstr *
1407SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
1408 MachineIRBuilder &MIRBuilder) {
1409 Register Reg = DT.find(TD, &MIRBuilder.getMF());
1410 if (Reg.isValid())
1411 return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
1412 return nullptr;
1413}
1414
1415// Returns nullptr if unable to recognize SPIRV type name
1417 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
1418 SPIRV::StorageClass::StorageClass SC,
1419 SPIRV::AccessQualifier::AccessQualifier AQ) {
1420 unsigned VecElts = 0;
1421 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1422
1423 // Parse strings representing either a SPIR-V or OpenCL builtin type.
1424 if (hasBuiltinTypePrefix(TypeStr))
1426 TypeStr.str(), MIRBuilder.getContext()),
1427 MIRBuilder, AQ);
1428
1429 // Parse type name in either "typeN" or "type vector[N]" format, where
1430 // N is the number of elements of the vector.
1431 Type *Ty;
1432
1433 Ty = parseBasicTypeName(TypeStr, Ctx);
1434 if (!Ty)
1435 // Unable to recognize SPIRV type name
1436 return nullptr;
1437
1438 auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
1439
1440 // Handle "type*" or "type* vector[N]".
1441 if (TypeStr.starts_with("*")) {
1442 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1443 TypeStr = TypeStr.substr(strlen("*"));
1444 }
1445
1446 // Handle "typeN*" or "type vector[N]*".
1447 bool IsPtrToVec = TypeStr.consume_back("*");
1448
1449 if (TypeStr.consume_front(" vector[")) {
1450 TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1451 }
1452 TypeStr.getAsInteger(10, VecElts);
1453 if (VecElts > 0)
1454 SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
1455
1456 if (IsPtrToVec)
1457 SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
1458
1459 return SpirvTy;
1460}
1461
1462SPIRVType *
1464 MachineIRBuilder &MIRBuilder) {
1465 return getOrCreateSPIRVType(
1467 MIRBuilder);
1468}
1469
1470SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1471 SPIRVType *SpirvType) {
1472 assert(CurMF == SpirvType->getMF());
1473 VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1474 SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);
1475 return SpirvType;
1476}
1477
1479 MachineInstr &I,
1480 const SPIRVInstrInfo &TII,
1481 unsigned SPIRVOPcode,
1482 Type *LLVMTy) {
1483 Register Reg = DT.find(LLVMTy, CurMF);
1484 if (Reg.isValid())
1485 return getSPIRVTypeForVReg(Reg);
1486 MachineBasicBlock &BB = *I.getParent();
1487 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRVOPcode))
1490 .addImm(0);
1491 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1492 return finishCreatingSPIRVType(LLVMTy, MIB);
1493}
1494
1496 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1497 // Maybe adjust bit width to keep DuplicateTracker consistent. Without
1498 // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for
1499 // example, the same "OpTypeInt 8" type for a series of LLVM integer types
1500 // with number of bits less than 8, causing duplicate type definitions.
1501 BitWidth = adjustOpTypeIntWidth(BitWidth);
1503 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1504}
1505
1507 unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1509 Type *LLVMTy;
1510 switch (BitWidth) {
1511 case 16:
1512 LLVMTy = Type::getHalfTy(Ctx);
1513 break;
1514 case 32:
1515 LLVMTy = Type::getFloatTy(Ctx);
1516 break;
1517 case 64:
1518 LLVMTy = Type::getDoubleTy(Ctx);
1519 break;
1520 default:
1521 llvm_unreachable("Bit width is of unexpected size.");
1522 }
1523 return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1524}
1525
1526SPIRVType *
1528 return getOrCreateSPIRVType(
1529 IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
1530 MIRBuilder);
1531}
1532
1533SPIRVType *
1535 const SPIRVInstrInfo &TII) {
1537 Register Reg = DT.find(LLVMTy, CurMF);
1538 if (Reg.isValid())
1539 return getSPIRVTypeForVReg(Reg);
1540 MachineBasicBlock &BB = *I.getParent();
1541 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1543 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1544 return finishCreatingSPIRVType(LLVMTy, MIB);
1545}
1546
1548 SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
1549 return getOrCreateSPIRVType(
1551 NumElements),
1552 MIRBuilder);
1553}
1554
1556 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1557 const SPIRVInstrInfo &TII) {
1558 Type *LLVMTy = FixedVectorType::get(
1559 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1560 Register Reg = DT.find(LLVMTy, CurMF);
1561 if (Reg.isValid())
1562 return getSPIRVTypeForVReg(Reg);
1563 MachineBasicBlock &BB = *I.getParent();
1564 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
1567 .addImm(NumElements);
1568 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1569 return finishCreatingSPIRVType(LLVMTy, MIB);
1570}
1571
1573 SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1574 const SPIRVInstrInfo &TII) {
1575 Type *LLVMTy = ArrayType::get(
1576 const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1577 Register Reg = DT.find(LLVMTy, CurMF);
1578 if (Reg.isValid())
1579 return getSPIRVTypeForVReg(Reg);
1580 MachineBasicBlock &BB = *I.getParent();
1581 SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, I, TII);
1582 Register Len = getOrCreateConstInt(NumElements, I, SpvTypeInt32, TII);
1583 auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1586 .addUse(Len);
1587 DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1588 return finishCreatingSPIRVType(LLVMTy, MIB);
1589}
1590
1592 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1593 SPIRV::StorageClass::StorageClass SC) {
1594 const Type *PointerElementType = getTypeForSPIRVType(BaseType);
1596 Type *LLVMTy = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1597 AddressSpace);
1598 // check if this type is already available
1599 Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1600 if (Reg.isValid())
1601 return getSPIRVTypeForVReg(Reg);
1602 // create a new type
1603 return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
1604 auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
1605 MIRBuilder.getDebugLoc(),
1606 MIRBuilder.getTII().get(SPIRV::OpTypePointer))
1608 .addImm(static_cast<uint32_t>(SC))
1610 DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1611 finishCreatingSPIRVType(LLVMTy, MIB);
1612 return MIB;
1613 });
1614}
1615
1618 SPIRV::StorageClass::StorageClass SC) {
1619 MachineIRBuilder MIRBuilder(I);
1620 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1621}
1622
1624 SPIRVType *SpvType,
1625 const SPIRVInstrInfo &TII) {
1626 assert(SpvType);
1627 const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1628 assert(LLVMTy);
1629 // Find a constant in DT or build a new one.
1630 UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1631 Register Res = DT.find(UV, CurMF);
1632 if (Res.isValid())
1633 return Res;
1634 LLT LLTy = LLT::scalar(64);
1636 CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);
1637 assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1638 DT.add(UV, CurMF, Res);
1639
1641 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1642 .addDef(Res)
1643 .addUse(getSPIRVTypeID(SpvType));
1644 const auto &ST = CurMF->getSubtarget();
1645 constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1646 *ST.getRegisterInfo(), *ST.getRegBankInfo());
1647 return Res;
1648}
1649
1650const TargetRegisterClass *
1652 unsigned Opcode = SpvType->getOpcode();
1653 switch (Opcode) {
1654 case SPIRV::OpTypeFloat:
1655 return &SPIRV::fIDRegClass;
1656 case SPIRV::OpTypePointer:
1657 return &SPIRV::pIDRegClass;
1658 case SPIRV::OpTypeVector: {
1659 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
1660 unsigned ElemOpcode = ElemType ? ElemType->getOpcode() : 0;
1661 if (ElemOpcode == SPIRV::OpTypeFloat)
1662 return &SPIRV::vfIDRegClass;
1663 if (ElemOpcode == SPIRV::OpTypePointer)
1664 return &SPIRV::vpIDRegClass;
1665 return &SPIRV::vIDRegClass;
1666 }
1667 }
1668 return &SPIRV::iIDRegClass;
1669}
1670
1671inline unsigned getAS(SPIRVType *SpvType) {
1673 static_cast<SPIRV::StorageClass::StorageClass>(
1674 SpvType->getOperand(1).getImm()));
1675}
1676
1678 unsigned Opcode = SpvType ? SpvType->getOpcode() : 0;
1679 switch (Opcode) {
1680 case SPIRV::OpTypeInt:
1681 case SPIRV::OpTypeFloat:
1682 case SPIRV::OpTypeBool:
1683 return LLT::scalar(getScalarOrVectorBitWidth(SpvType));
1684 case SPIRV::OpTypePointer:
1685 return LLT::pointer(getAS(SpvType), getPointerSize());
1686 case SPIRV::OpTypeVector: {
1687 SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
1688 LLT ET;
1689 switch (ElemType ? ElemType->getOpcode() : 0) {
1690 case SPIRV::OpTypePointer:
1691 ET = LLT::pointer(getAS(ElemType), getPointerSize());
1692 break;
1693 case SPIRV::OpTypeInt:
1694 case SPIRV::OpTypeFloat:
1695 case SPIRV::OpTypeBool:
1696 ET = LLT::scalar(getScalarOrVectorBitWidth(ElemType));
1697 break;
1698 default:
1699 ET = LLT::scalar(64);
1700 }
1701 return LLT::fixed_vector(
1702 static_cast<unsigned>(SpvType->getOperand(2).getImm()), ET);
1703 }
1704 }
1705 return LLT::scalar(64);
1706}
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:1835
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
if(PassOpts->AAPipeline)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
static Register createTypeVReg(MachineRegisterInfo &MRI)
unsigned getAS(SPIRVType *SpvType)
static std::string GetSpirvImageTypeName(const SPIRVType *Type, MachineIRBuilder &MIRBuilder, const std::string &Prefix)
static std::string buildSpirvTypeName(const SPIRVType *Type, MachineIRBuilder &MIRBuilder)
unsigned typeToAddressSpace(const Type *Ty)
bool isPosZero() const
Definition: APFloat.h:1456
Class for arbitrary precision integers.
Definition: APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1520
Class to represent array types.
Definition: DerivedTypes.h:395
uint64_t getNumElements() const
Definition: DerivedTypes.h:407
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Type * getElementType() const
Definition: DerivedTypes.h:408
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:271
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:157
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Definition: Constants.cpp:1826
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition: Constants.h:480
static Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
Definition: Constants.cpp:1472
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:1771
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition: Constants.cpp:90
This class represents an Operation in the Expression.
Class to represent fixed width SIMD vectors.
Definition: DerivedTypes.h:563
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition: Type.cpp:791
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
Definition: GlobalObject.h:79
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:42
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:311
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.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
LLVMContext & getContext() const
const TargetInstrInfo & getTII()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
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.
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:575
iterator_range< mop_iterator > uses()
Returns a range that includes all operands which may be register uses.
Definition: MachineInstr.h:739
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:728
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:585
const ConstantInt * getCImm() const
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:1878
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)
Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, uint32_t Set, uint32_t Binding, MachineIRBuilder &MIRBuilder)
SPIRVType * assignFloatTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
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)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
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)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
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)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
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 * getResultType(Register VReg)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
LLT getRegType(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVArrayType(SPIRVType *BaseType, unsigned NumElements, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
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
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR=true, bool ZeroAsNull=true)
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:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:655
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:470
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:571
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:265
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition: StringRef.h:635
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:297
Class to represent struct types.
Definition: DerivedTypes.h:218
ArrayRef< Type * > elements() const
Definition: DerivedTypes.h:357
bool isPacked() const
Definition: DerivedTypes.h:284
bool hasName() const
Return true if this is a named struct that has a non-empty name.
Definition: DerivedTypes.h:326
StringRef getName() const
Return the name for this struct type if it has an identity.
Definition: Type.cpp:689
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:744
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:270
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:261
Type * getArrayElementType() const
Definition: Type.h:411
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 Type * getFloatTy(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:237
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
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
'undef' values are things that do not have specified contents.
Definition: Constants.h:1412
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1859
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:665
Type * getElementType() const
Definition: DerivedTypes.h:460
#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:103
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
Definition: SPIRVUtils.h:297
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:261
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:83
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
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.h:162
bool getSpirvBuiltInIdByName(llvm::StringRef Name, SPIRV::BuiltIn::BuiltIn &BI)
bool isTypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:245
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:130
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:352
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:436
bool isPointerTy(const Type *T)
Definition: SPIRVUtils.h:255
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
Definition: SPIRVUtils.cpp:197
const Type * unifyPtrType(const Type *Ty)
Definition: SPIRVUtils.h:379
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:211
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Definition: SPIRVUtils.cpp:459
DWARFExpression::Operation Op
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:217
bool hasBuiltinTypePrefix(StringRef Name)
Definition: SPIRVUtils.cpp:429
bool isPointerTyOrWrapper(const Type *Ty)
Definition: SPIRVUtils.h:304
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:54
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
Definition: SPIRVUtils.cpp:704
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:149
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