xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===-- SPIRVGlobalRegistry.cpp - SPIR-V Global Registry --------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This file contains the implementation of the SPIRVGlobalRegistry class,
1081ad6265SDimitry Andric // which is used to maintain rich type information required for SPIR-V even
1181ad6265SDimitry Andric // after lowering from LLVM IR to GMIR. It can convert an llvm::Type into
1281ad6265SDimitry Andric // an OpTypeXXX instruction, and map it to a virtual register. Also it builds
1381ad6265SDimitry Andric // and supports consistency of constants and global variables.
1481ad6265SDimitry Andric //
1581ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1681ad6265SDimitry Andric 
1781ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h"
1881ad6265SDimitry Andric #include "SPIRV.h"
19bdd1243dSDimitry Andric #include "SPIRVBuiltins.h"
2081ad6265SDimitry Andric #include "SPIRVSubtarget.h"
2181ad6265SDimitry Andric #include "SPIRVTargetMachine.h"
2281ad6265SDimitry Andric #include "SPIRVUtils.h"
23*0fca6ea1SDimitry Andric #include "llvm/ADT/APInt.h"
24*0fca6ea1SDimitry Andric #include "llvm/IR/Constants.h"
25*0fca6ea1SDimitry Andric #include "llvm/IR/Type.h"
26*0fca6ea1SDimitry Andric #include "llvm/Support/Casting.h"
27*0fca6ea1SDimitry Andric #include <cassert>
2881ad6265SDimitry Andric 
2981ad6265SDimitry Andric using namespace llvm;
3081ad6265SDimitry Andric SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize)
31*0fca6ea1SDimitry Andric     : PointerSize(PointerSize), Bound(0) {}
3281ad6265SDimitry Andric 
33fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignIntTypeToVReg(unsigned BitWidth,
34fcaf7f86SDimitry Andric                                                     Register VReg,
35fcaf7f86SDimitry Andric                                                     MachineInstr &I,
36fcaf7f86SDimitry Andric                                                     const SPIRVInstrInfo &TII) {
37fcaf7f86SDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
38fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
39fcaf7f86SDimitry Andric   return SpirvType;
40fcaf7f86SDimitry Andric }
41fcaf7f86SDimitry Andric 
42*0fca6ea1SDimitry Andric SPIRVType *
43*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::assignFloatTypeToVReg(unsigned BitWidth, Register VReg,
44*0fca6ea1SDimitry Andric                                            MachineInstr &I,
45*0fca6ea1SDimitry Andric                                            const SPIRVInstrInfo &TII) {
46*0fca6ea1SDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVFloatType(BitWidth, I, TII);
47*0fca6ea1SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
48*0fca6ea1SDimitry Andric   return SpirvType;
49*0fca6ea1SDimitry Andric }
50*0fca6ea1SDimitry Andric 
51fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignVectTypeToVReg(
52fcaf7f86SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
53fcaf7f86SDimitry Andric     const SPIRVInstrInfo &TII) {
54fcaf7f86SDimitry Andric   SPIRVType *SpirvType =
55fcaf7f86SDimitry Andric       getOrCreateSPIRVVectorType(BaseType, NumElements, I, TII);
56fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
57fcaf7f86SDimitry Andric   return SpirvType;
58fcaf7f86SDimitry Andric }
59fcaf7f86SDimitry Andric 
6081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignTypeToVReg(
6181ad6265SDimitry Andric     const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
62bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
6381ad6265SDimitry Andric   SPIRVType *SpirvType =
6481ad6265SDimitry Andric       getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
6581ad6265SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
6681ad6265SDimitry Andric   return SpirvType;
6781ad6265SDimitry Andric }
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric void SPIRVGlobalRegistry::assignSPIRVTypeToVReg(SPIRVType *SpirvType,
7081ad6265SDimitry Andric                                                 Register VReg,
7181ad6265SDimitry Andric                                                 MachineFunction &MF) {
7281ad6265SDimitry Andric   VRegToTypeMap[&MF][VReg] = SpirvType;
7381ad6265SDimitry Andric }
7481ad6265SDimitry Andric 
7581ad6265SDimitry Andric static Register createTypeVReg(MachineIRBuilder &MIRBuilder) {
7681ad6265SDimitry Andric   auto &MRI = MIRBuilder.getMF().getRegInfo();
7781ad6265SDimitry Andric   auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
7881ad6265SDimitry Andric   MRI.setRegClass(Res, &SPIRV::TYPERegClass);
7981ad6265SDimitry Andric   return Res;
8081ad6265SDimitry Andric }
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric static Register createTypeVReg(MachineRegisterInfo &MRI) {
8381ad6265SDimitry Andric   auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
8481ad6265SDimitry Andric   MRI.setRegClass(Res, &SPIRV::TYPERegClass);
8581ad6265SDimitry Andric   return Res;
8681ad6265SDimitry Andric }
8781ad6265SDimitry Andric 
8881ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
8981ad6265SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
9081ad6265SDimitry Andric       .addDef(createTypeVReg(MIRBuilder));
9181ad6265SDimitry Andric }
9281ad6265SDimitry Andric 
93*0fca6ea1SDimitry Andric unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {
94*0fca6ea1SDimitry Andric   if (Width > 64)
95*0fca6ea1SDimitry Andric     report_fatal_error("Unsupported integer width!");
96*0fca6ea1SDimitry Andric   const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());
97*0fca6ea1SDimitry Andric   if (ST.canUseExtension(
98*0fca6ea1SDimitry Andric           SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers))
99*0fca6ea1SDimitry Andric     return Width;
100*0fca6ea1SDimitry Andric   if (Width <= 8)
101*0fca6ea1SDimitry Andric     Width = 8;
102*0fca6ea1SDimitry Andric   else if (Width <= 16)
103*0fca6ea1SDimitry Andric     Width = 16;
104*0fca6ea1SDimitry Andric   else if (Width <= 32)
105*0fca6ea1SDimitry Andric     Width = 32;
106*0fca6ea1SDimitry Andric   else
107*0fca6ea1SDimitry Andric     Width = 64;
108*0fca6ea1SDimitry Andric   return Width;
109*0fca6ea1SDimitry Andric }
110*0fca6ea1SDimitry Andric 
111*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,
11281ad6265SDimitry Andric                                              MachineIRBuilder &MIRBuilder,
11381ad6265SDimitry Andric                                              bool IsSigned) {
114*0fca6ea1SDimitry Andric   Width = adjustOpTypeIntWidth(Width);
1155f757f3fSDimitry Andric   const SPIRVSubtarget &ST =
1165f757f3fSDimitry Andric       cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
1175f757f3fSDimitry Andric   if (ST.canUseExtension(
1185f757f3fSDimitry Andric           SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
1195f757f3fSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpExtension)
1205f757f3fSDimitry Andric         .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
1215f757f3fSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpCapability)
1225f757f3fSDimitry Andric         .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
123*0fca6ea1SDimitry Andric   }
12481ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
12581ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
12681ad6265SDimitry Andric                  .addImm(Width)
12781ad6265SDimitry Andric                  .addImm(IsSigned ? 1 : 0);
12881ad6265SDimitry Andric   return MIB;
12981ad6265SDimitry Andric }
13081ad6265SDimitry Andric 
13181ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
13281ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder) {
13381ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
13481ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
13581ad6265SDimitry Andric                  .addImm(Width);
13681ad6265SDimitry Andric   return MIB;
13781ad6265SDimitry Andric }
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
14081ad6265SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
14181ad6265SDimitry Andric       .addDef(createTypeVReg(MIRBuilder));
14281ad6265SDimitry Andric }
14381ad6265SDimitry Andric 
14481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
14581ad6265SDimitry Andric                                                 SPIRVType *ElemType,
14681ad6265SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
14781ad6265SDimitry Andric   auto EleOpc = ElemType->getOpcode();
148*0fca6ea1SDimitry Andric   (void)EleOpc;
14981ad6265SDimitry Andric   assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
15081ad6265SDimitry Andric           EleOpc == SPIRV::OpTypeBool) &&
15181ad6265SDimitry Andric          "Invalid vector element type");
15281ad6265SDimitry Andric 
15381ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
15481ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
15581ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
15681ad6265SDimitry Andric                  .addImm(NumElems);
15781ad6265SDimitry Andric   return MIB;
15881ad6265SDimitry Andric }
15981ad6265SDimitry Andric 
160fcaf7f86SDimitry Andric std::tuple<Register, ConstantInt *, bool>
161fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
162fcaf7f86SDimitry Andric                                             MachineIRBuilder *MIRBuilder,
163fcaf7f86SDimitry Andric                                             MachineInstr *I,
164fcaf7f86SDimitry Andric                                             const SPIRVInstrInfo *TII) {
165fcaf7f86SDimitry Andric   const IntegerType *LLVMIntTy;
166fcaf7f86SDimitry Andric   if (SpvType)
167fcaf7f86SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
168fcaf7f86SDimitry Andric   else
169fcaf7f86SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(CurMF->getFunction().getContext());
170fcaf7f86SDimitry Andric   bool NewInstr = false;
171fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
172fcaf7f86SDimitry Andric   ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
173fcaf7f86SDimitry Andric   Register Res = DT.find(CI, CurMF);
174fcaf7f86SDimitry Andric   if (!Res.isValid()) {
175fcaf7f86SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
176*0fca6ea1SDimitry Andric     // TODO: handle cases where the type is not 32bit wide
177*0fca6ea1SDimitry Andric     // TODO: https://github.com/llvm/llvm-project/issues/88129
178fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
179fcaf7f86SDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
18006c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
181fcaf7f86SDimitry Andric     if (MIRBuilder)
182fcaf7f86SDimitry Andric       assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
183fcaf7f86SDimitry Andric     else
184fcaf7f86SDimitry Andric       assignIntTypeToVReg(BitWidth, Res, *I, *TII);
185fcaf7f86SDimitry Andric     DT.add(CI, CurMF, Res);
186fcaf7f86SDimitry Andric     NewInstr = true;
187fcaf7f86SDimitry Andric   }
188fcaf7f86SDimitry Andric   return std::make_tuple(Res, CI, NewInstr);
189fcaf7f86SDimitry Andric }
190fcaf7f86SDimitry Andric 
191*0fca6ea1SDimitry Andric std::tuple<Register, ConstantFP *, bool, unsigned>
192*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::getOrCreateConstFloatReg(APFloat Val, SPIRVType *SpvType,
193*0fca6ea1SDimitry Andric                                               MachineIRBuilder *MIRBuilder,
194*0fca6ea1SDimitry Andric                                               MachineInstr *I,
195*0fca6ea1SDimitry Andric                                               const SPIRVInstrInfo *TII) {
196*0fca6ea1SDimitry Andric   const Type *LLVMFloatTy;
197*0fca6ea1SDimitry Andric   LLVMContext &Ctx = CurMF->getFunction().getContext();
198*0fca6ea1SDimitry Andric   unsigned BitWidth = 32;
199*0fca6ea1SDimitry Andric   if (SpvType)
200*0fca6ea1SDimitry Andric     LLVMFloatTy = getTypeForSPIRVType(SpvType);
201*0fca6ea1SDimitry Andric   else {
202*0fca6ea1SDimitry Andric     LLVMFloatTy = Type::getFloatTy(Ctx);
203*0fca6ea1SDimitry Andric     if (MIRBuilder)
204*0fca6ea1SDimitry Andric       SpvType = getOrCreateSPIRVType(LLVMFloatTy, *MIRBuilder);
205*0fca6ea1SDimitry Andric   }
206*0fca6ea1SDimitry Andric   bool NewInstr = false;
207*0fca6ea1SDimitry Andric   // Find a constant in DT or build a new one.
208*0fca6ea1SDimitry Andric   auto *const CI = ConstantFP::get(Ctx, Val);
209*0fca6ea1SDimitry Andric   Register Res = DT.find(CI, CurMF);
210*0fca6ea1SDimitry Andric   if (!Res.isValid()) {
211*0fca6ea1SDimitry Andric     if (SpvType)
212*0fca6ea1SDimitry Andric       BitWidth = getScalarOrVectorBitWidth(SpvType);
213*0fca6ea1SDimitry Andric     // TODO: handle cases where the type is not 32bit wide
214*0fca6ea1SDimitry Andric     // TODO: https://github.com/llvm/llvm-project/issues/88129
215*0fca6ea1SDimitry Andric     LLT LLTy = LLT::scalar(32);
216*0fca6ea1SDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
217*0fca6ea1SDimitry Andric     CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
218*0fca6ea1SDimitry Andric     if (MIRBuilder)
219*0fca6ea1SDimitry Andric       assignTypeToVReg(LLVMFloatTy, Res, *MIRBuilder);
220*0fca6ea1SDimitry Andric     else
221*0fca6ea1SDimitry Andric       assignFloatTypeToVReg(BitWidth, Res, *I, *TII);
222*0fca6ea1SDimitry Andric     DT.add(CI, CurMF, Res);
223*0fca6ea1SDimitry Andric     NewInstr = true;
224*0fca6ea1SDimitry Andric   }
225*0fca6ea1SDimitry Andric   return std::make_tuple(Res, CI, NewInstr, BitWidth);
226*0fca6ea1SDimitry Andric }
227*0fca6ea1SDimitry Andric 
228*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,
229*0fca6ea1SDimitry Andric                                                  SPIRVType *SpvType,
230*0fca6ea1SDimitry Andric                                                  const SPIRVInstrInfo &TII,
231*0fca6ea1SDimitry Andric                                                  bool ZeroAsNull) {
232*0fca6ea1SDimitry Andric   assert(SpvType);
233*0fca6ea1SDimitry Andric   ConstantFP *CI;
234*0fca6ea1SDimitry Andric   Register Res;
235*0fca6ea1SDimitry Andric   bool New;
236*0fca6ea1SDimitry Andric   unsigned BitWidth;
237*0fca6ea1SDimitry Andric   std::tie(Res, CI, New, BitWidth) =
238*0fca6ea1SDimitry Andric       getOrCreateConstFloatReg(Val, SpvType, nullptr, &I, &TII);
239*0fca6ea1SDimitry Andric   // If we have found Res register which is defined by the passed G_CONSTANT
240*0fca6ea1SDimitry Andric   // machine instruction, a new constant instruction should be created.
241*0fca6ea1SDimitry Andric   if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
242*0fca6ea1SDimitry Andric     return Res;
243*0fca6ea1SDimitry Andric   MachineInstrBuilder MIB;
244*0fca6ea1SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
245*0fca6ea1SDimitry Andric   // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)
246*0fca6ea1SDimitry Andric   if (Val.isPosZero() && ZeroAsNull) {
247*0fca6ea1SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
248*0fca6ea1SDimitry Andric               .addDef(Res)
249*0fca6ea1SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
250*0fca6ea1SDimitry Andric   } else {
251*0fca6ea1SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantF))
252*0fca6ea1SDimitry Andric               .addDef(Res)
253*0fca6ea1SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
254*0fca6ea1SDimitry Andric     addNumImm(
255*0fca6ea1SDimitry Andric         APInt(BitWidth, CI->getValueAPF().bitcastToAPInt().getZExtValue()),
256*0fca6ea1SDimitry Andric         MIB);
257*0fca6ea1SDimitry Andric   }
258*0fca6ea1SDimitry Andric   const auto &ST = CurMF->getSubtarget();
259*0fca6ea1SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
260*0fca6ea1SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
261*0fca6ea1SDimitry Andric   return Res;
262*0fca6ea1SDimitry Andric }
263*0fca6ea1SDimitry Andric 
264fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
265fcaf7f86SDimitry Andric                                                   SPIRVType *SpvType,
266*0fca6ea1SDimitry Andric                                                   const SPIRVInstrInfo &TII,
267*0fca6ea1SDimitry Andric                                                   bool ZeroAsNull) {
268fcaf7f86SDimitry Andric   assert(SpvType);
269fcaf7f86SDimitry Andric   ConstantInt *CI;
270fcaf7f86SDimitry Andric   Register Res;
271fcaf7f86SDimitry Andric   bool New;
272fcaf7f86SDimitry Andric   std::tie(Res, CI, New) =
273fcaf7f86SDimitry Andric       getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
274fcaf7f86SDimitry Andric   // If we have found Res register which is defined by the passed G_CONSTANT
275fcaf7f86SDimitry Andric   // machine instruction, a new constant instruction should be created.
276fcaf7f86SDimitry Andric   if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
277fcaf7f86SDimitry Andric     return Res;
278fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
279fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
280*0fca6ea1SDimitry Andric   if (Val || !ZeroAsNull) {
281fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
282fcaf7f86SDimitry Andric               .addDef(Res)
283fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
284fcaf7f86SDimitry Andric     addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
285fcaf7f86SDimitry Andric   } else {
286fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
287fcaf7f86SDimitry Andric               .addDef(Res)
288fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
289fcaf7f86SDimitry Andric   }
290fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
291fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
292fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
293fcaf7f86SDimitry Andric   return Res;
294fcaf7f86SDimitry Andric }
295fcaf7f86SDimitry Andric 
29681ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
29781ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
29881ad6265SDimitry Andric                                                SPIRVType *SpvType,
29981ad6265SDimitry Andric                                                bool EmitIR) {
30081ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
30181ad6265SDimitry Andric   const IntegerType *LLVMIntTy;
30281ad6265SDimitry Andric   if (SpvType)
30381ad6265SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
30481ad6265SDimitry Andric   else
30581ad6265SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
30681ad6265SDimitry Andric   // Find a constant in DT or build a new one.
30781ad6265SDimitry Andric   const auto ConstInt =
30881ad6265SDimitry Andric       ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
309753f127fSDimitry Andric   Register Res = DT.find(ConstInt, &MF);
310753f127fSDimitry Andric   if (!Res.isValid()) {
31181ad6265SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
312fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
313fcaf7f86SDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
31406c3fb27SDimitry Andric     MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
315fcaf7f86SDimitry Andric     assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
316fcaf7f86SDimitry Andric                      SPIRV::AccessQualifier::ReadWrite, EmitIR);
317fcaf7f86SDimitry Andric     DT.add(ConstInt, &MIRBuilder.getMF(), Res);
318fcaf7f86SDimitry Andric     if (EmitIR) {
31981ad6265SDimitry Andric       MIRBuilder.buildConstant(Res, *ConstInt);
320fcaf7f86SDimitry Andric     } else {
321*0fca6ea1SDimitry Andric       if (!SpvType)
322*0fca6ea1SDimitry Andric         SpvType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
323fcaf7f86SDimitry Andric       MachineInstrBuilder MIB;
324fcaf7f86SDimitry Andric       if (Val) {
325fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
32681ad6265SDimitry Andric                   .addDef(Res)
327fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
328fcaf7f86SDimitry Andric         addNumImm(APInt(BitWidth, Val), MIB);
329fcaf7f86SDimitry Andric       } else {
330fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
331fcaf7f86SDimitry Andric                   .addDef(Res)
332fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
333fcaf7f86SDimitry Andric       }
334fcaf7f86SDimitry Andric       const auto &Subtarget = CurMF->getSubtarget();
335fcaf7f86SDimitry Andric       constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
336fcaf7f86SDimitry Andric                                        *Subtarget.getRegisterInfo(),
337fcaf7f86SDimitry Andric                                        *Subtarget.getRegBankInfo());
338fcaf7f86SDimitry Andric     }
339753f127fSDimitry Andric   }
34081ad6265SDimitry Andric   return Res;
34181ad6265SDimitry Andric }
34281ad6265SDimitry Andric 
34381ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,
34481ad6265SDimitry Andric                                               MachineIRBuilder &MIRBuilder,
34581ad6265SDimitry Andric                                               SPIRVType *SpvType) {
34681ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
3475f757f3fSDimitry Andric   auto &Ctx = MF.getFunction().getContext();
3485f757f3fSDimitry Andric   if (!SpvType) {
3495f757f3fSDimitry Andric     const Type *LLVMFPTy = Type::getFloatTy(Ctx);
3505f757f3fSDimitry Andric     SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
35181ad6265SDimitry Andric   }
35281ad6265SDimitry Andric   // Find a constant in DT or build a new one.
3535f757f3fSDimitry Andric   const auto ConstFP = ConstantFP::get(Ctx, Val);
354753f127fSDimitry Andric   Register Res = DT.find(ConstFP, &MF);
355753f127fSDimitry Andric   if (!Res.isValid()) {
3565f757f3fSDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(32));
35706c3fb27SDimitry Andric     MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
3585f757f3fSDimitry Andric     assignSPIRVTypeToVReg(SpvType, Res, MF);
359fcaf7f86SDimitry Andric     DT.add(ConstFP, &MF, Res);
3605f757f3fSDimitry Andric 
3615f757f3fSDimitry Andric     MachineInstrBuilder MIB;
3625f757f3fSDimitry Andric     MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
3635f757f3fSDimitry Andric               .addDef(Res)
3645f757f3fSDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
3655f757f3fSDimitry Andric     addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
366753f127fSDimitry Andric   }
3675f757f3fSDimitry Andric 
36881ad6265SDimitry Andric   return Res;
36981ad6265SDimitry Andric }
37081ad6265SDimitry Andric 
371*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateBaseRegister(Constant *Val,
372*0fca6ea1SDimitry Andric                                                       MachineInstr &I,
373*0fca6ea1SDimitry Andric                                                       SPIRVType *SpvType,
374*0fca6ea1SDimitry Andric                                                       const SPIRVInstrInfo &TII,
375*0fca6ea1SDimitry Andric                                                       unsigned BitWidth) {
376*0fca6ea1SDimitry Andric   SPIRVType *Type = SpvType;
377*0fca6ea1SDimitry Andric   if (SpvType->getOpcode() == SPIRV::OpTypeVector ||
378*0fca6ea1SDimitry Andric       SpvType->getOpcode() == SPIRV::OpTypeArray) {
379*0fca6ea1SDimitry Andric     auto EleTypeReg = SpvType->getOperand(1).getReg();
380*0fca6ea1SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
381*0fca6ea1SDimitry Andric   }
382*0fca6ea1SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeFloat) {
383*0fca6ea1SDimitry Andric     SPIRVType *SpvBaseType = getOrCreateSPIRVFloatType(BitWidth, I, TII);
384*0fca6ea1SDimitry Andric     return getOrCreateConstFP(dyn_cast<ConstantFP>(Val)->getValue(), I,
385*0fca6ea1SDimitry Andric                               SpvBaseType, TII);
386*0fca6ea1SDimitry Andric   }
387*0fca6ea1SDimitry Andric   assert(Type->getOpcode() == SPIRV::OpTypeInt);
388fcaf7f86SDimitry Andric   SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
389*0fca6ea1SDimitry Andric   return getOrCreateConstInt(Val->getUniqueInteger().getSExtValue(), I,
390*0fca6ea1SDimitry Andric                              SpvBaseType, TII);
391*0fca6ea1SDimitry Andric }
392*0fca6ea1SDimitry Andric 
393*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(
394*0fca6ea1SDimitry Andric     Constant *Val, MachineInstr &I, SPIRVType *SpvType,
395*0fca6ea1SDimitry Andric     const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
396*0fca6ea1SDimitry Andric     unsigned ElemCnt, bool ZeroAsNull) {
397*0fca6ea1SDimitry Andric   // Find a constant vector or array in DT or build a new one.
398*0fca6ea1SDimitry Andric   Register Res = DT.find(CA, CurMF);
399*0fca6ea1SDimitry Andric   // If no values are attached, the composite is null constant.
400*0fca6ea1SDimitry Andric   bool IsNull = Val->isNullValue() && ZeroAsNull;
401*0fca6ea1SDimitry Andric   if (!Res.isValid()) {
402fcaf7f86SDimitry Andric     // SpvScalConst should be created before SpvVecConst to avoid undefined ID
403fcaf7f86SDimitry Andric     // error on validation.
404fcaf7f86SDimitry Andric     // TODO: can moved below once sorting of types/consts/defs is implemented.
405fcaf7f86SDimitry Andric     Register SpvScalConst;
406*0fca6ea1SDimitry Andric     if (!IsNull)
407*0fca6ea1SDimitry Andric       SpvScalConst = getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth);
408*0fca6ea1SDimitry Andric 
409*0fca6ea1SDimitry Andric     // TODO: handle cases where the type is not 32bit wide
410*0fca6ea1SDimitry Andric     // TODO: https://github.com/llvm/llvm-project/issues/88129
411fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
412fcaf7f86SDimitry Andric     Register SpvVecConst =
413fcaf7f86SDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
41406c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
415bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
416bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
417fcaf7f86SDimitry Andric     MachineInstrBuilder MIB;
418fcaf7f86SDimitry Andric     MachineBasicBlock &BB = *I.getParent();
419*0fca6ea1SDimitry Andric     if (!IsNull) {
420fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
421fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
422fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
423fcaf7f86SDimitry Andric       for (unsigned i = 0; i < ElemCnt; ++i)
424fcaf7f86SDimitry Andric         MIB.addUse(SpvScalConst);
425fcaf7f86SDimitry Andric     } else {
426fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
427fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
428fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
429fcaf7f86SDimitry Andric     }
430fcaf7f86SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
431fcaf7f86SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
432fcaf7f86SDimitry Andric                                      *Subtarget.getRegisterInfo(),
433fcaf7f86SDimitry Andric                                      *Subtarget.getRegBankInfo());
434fcaf7f86SDimitry Andric     return SpvVecConst;
435fcaf7f86SDimitry Andric   }
436fcaf7f86SDimitry Andric   return Res;
437fcaf7f86SDimitry Andric }
438fcaf7f86SDimitry Andric 
439*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstVector(uint64_t Val,
440*0fca6ea1SDimitry Andric                                                      MachineInstr &I,
441bdd1243dSDimitry Andric                                                      SPIRVType *SpvType,
442*0fca6ea1SDimitry Andric                                                      const SPIRVInstrInfo &TII,
443*0fca6ea1SDimitry Andric                                                      bool ZeroAsNull) {
444bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
445bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
446bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
447bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
448*0fca6ea1SDimitry Andric   assert(LLVMBaseTy->isIntegerTy());
449*0fca6ea1SDimitry Andric   auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);
450*0fca6ea1SDimitry Andric   auto *ConstVec =
451*0fca6ea1SDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
452bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
453*0fca6ea1SDimitry Andric   return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
454*0fca6ea1SDimitry Andric                                     SpvType->getOperand(2).getImm(),
455*0fca6ea1SDimitry Andric                                     ZeroAsNull);
456bdd1243dSDimitry Andric }
457bdd1243dSDimitry Andric 
458*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstVector(APFloat Val,
459*0fca6ea1SDimitry Andric                                                      MachineInstr &I,
460bdd1243dSDimitry Andric                                                      SPIRVType *SpvType,
461*0fca6ea1SDimitry Andric                                                      const SPIRVInstrInfo &TII,
462*0fca6ea1SDimitry Andric                                                      bool ZeroAsNull) {
463*0fca6ea1SDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
464*0fca6ea1SDimitry Andric   assert(LLVMTy->isVectorTy());
465*0fca6ea1SDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
466*0fca6ea1SDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
467*0fca6ea1SDimitry Andric   assert(LLVMBaseTy->isFloatingPointTy());
468*0fca6ea1SDimitry Andric   auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);
469*0fca6ea1SDimitry Andric   auto *ConstVec =
470*0fca6ea1SDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);
471*0fca6ea1SDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
472*0fca6ea1SDimitry Andric   return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,
473*0fca6ea1SDimitry Andric                                     SpvType->getOperand(2).getImm(),
474*0fca6ea1SDimitry Andric                                     ZeroAsNull);
475*0fca6ea1SDimitry Andric }
476*0fca6ea1SDimitry Andric 
477*0fca6ea1SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstIntArray(
478*0fca6ea1SDimitry Andric     uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,
479bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII) {
480bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
481bdd1243dSDimitry Andric   assert(LLVMTy->isArrayTy());
482bdd1243dSDimitry Andric   const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
483bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMArrTy->getElementType();
484*0fca6ea1SDimitry Andric   Constant *CI = ConstantInt::get(LLVMBaseTy, Val);
485bdd1243dSDimitry Andric   SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
486bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
487*0fca6ea1SDimitry Andric   // The following is reasonably unique key that is better that [Val]. The naive
488*0fca6ea1SDimitry Andric   // alternative would be something along the lines of:
489*0fca6ea1SDimitry Andric   //   SmallVector<Constant *> NumCI(Num, CI);
490*0fca6ea1SDimitry Andric   //   Constant *UniqueKey =
491*0fca6ea1SDimitry Andric   //     ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);
492*0fca6ea1SDimitry Andric   // that would be a truly unique but dangerous key, because it could lead to
493*0fca6ea1SDimitry Andric   // the creation of constants of arbitrary length (that is, the parameter of
494*0fca6ea1SDimitry Andric   // memset) which were missing in the original module.
495*0fca6ea1SDimitry Andric   Constant *UniqueKey = ConstantStruct::getAnon(
496*0fca6ea1SDimitry Andric       {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),
497*0fca6ea1SDimitry Andric        ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});
498*0fca6ea1SDimitry Andric   return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,
499bdd1243dSDimitry Andric                                     LLVMArrTy->getNumElements());
500bdd1243dSDimitry Andric }
501bdd1243dSDimitry Andric 
502bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
503bdd1243dSDimitry Andric     uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
504bdd1243dSDimitry Andric     Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
505bdd1243dSDimitry Andric   Register Res = DT.find(CA, CurMF);
506bdd1243dSDimitry Andric   if (!Res.isValid()) {
507bdd1243dSDimitry Andric     Register SpvScalConst;
508bdd1243dSDimitry Andric     if (Val || EmitIR) {
509bdd1243dSDimitry Andric       SPIRVType *SpvBaseType =
510bdd1243dSDimitry Andric           getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
511bdd1243dSDimitry Andric       SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
512bdd1243dSDimitry Andric     }
513bdd1243dSDimitry Andric     LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
514bdd1243dSDimitry Andric     Register SpvVecConst =
515bdd1243dSDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
51606c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
517bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
518bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
519bdd1243dSDimitry Andric     if (EmitIR) {
520bdd1243dSDimitry Andric       MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
521bdd1243dSDimitry Andric     } else {
522bdd1243dSDimitry Andric       if (Val) {
523bdd1243dSDimitry Andric         auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
524bdd1243dSDimitry Andric                        .addDef(SpvVecConst)
525bdd1243dSDimitry Andric                        .addUse(getSPIRVTypeID(SpvType));
526bdd1243dSDimitry Andric         for (unsigned i = 0; i < ElemCnt; ++i)
527bdd1243dSDimitry Andric           MIB.addUse(SpvScalConst);
528bdd1243dSDimitry Andric       } else {
529bdd1243dSDimitry Andric         MIRBuilder.buildInstr(SPIRV::OpConstantNull)
530bdd1243dSDimitry Andric             .addDef(SpvVecConst)
531bdd1243dSDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
532bdd1243dSDimitry Andric       }
533bdd1243dSDimitry Andric     }
534bdd1243dSDimitry Andric     return SpvVecConst;
535bdd1243dSDimitry Andric   }
536bdd1243dSDimitry Andric   return Res;
537bdd1243dSDimitry Andric }
538bdd1243dSDimitry Andric 
539bdd1243dSDimitry Andric Register
540bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val,
541bdd1243dSDimitry Andric                                               MachineIRBuilder &MIRBuilder,
542bdd1243dSDimitry Andric                                               SPIRVType *SpvType, bool EmitIR) {
543bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
544bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
545bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
546bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
547bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
548bdd1243dSDimitry Andric   auto ConstVec =
549bdd1243dSDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
550bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
551bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
552bdd1243dSDimitry Andric                                        ConstVec, BW,
553bdd1243dSDimitry Andric                                        SpvType->getOperand(2).getImm());
554bdd1243dSDimitry Andric }
555bdd1243dSDimitry Andric 
556bdd1243dSDimitry Andric Register
557bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
558bdd1243dSDimitry Andric                                              SPIRVType *SpvType) {
559bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
560*0fca6ea1SDimitry Andric   const TypedPointerType *LLVMPtrTy = cast<TypedPointerType>(LLVMTy);
561bdd1243dSDimitry Andric   // Find a constant in DT or build a new one.
562*0fca6ea1SDimitry Andric   Constant *CP = ConstantPointerNull::get(PointerType::get(
563*0fca6ea1SDimitry Andric       LLVMPtrTy->getElementType(), LLVMPtrTy->getAddressSpace()));
564bdd1243dSDimitry Andric   Register Res = DT.find(CP, CurMF);
565bdd1243dSDimitry Andric   if (!Res.isValid()) {
566bdd1243dSDimitry Andric     LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
567bdd1243dSDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
56806c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
569bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
570bdd1243dSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpConstantNull)
571bdd1243dSDimitry Andric         .addDef(Res)
572bdd1243dSDimitry Andric         .addUse(getSPIRVTypeID(SpvType));
573bdd1243dSDimitry Andric     DT.add(CP, CurMF, Res);
574bdd1243dSDimitry Andric   }
575bdd1243dSDimitry Andric   return Res;
576bdd1243dSDimitry Andric }
577bdd1243dSDimitry Andric 
578bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::buildConstantSampler(
579bdd1243dSDimitry Andric     Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
580bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
581bdd1243dSDimitry Andric   SPIRVType *SampTy;
582bdd1243dSDimitry Andric   if (SpvType)
583bdd1243dSDimitry Andric     SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
584*0fca6ea1SDimitry Andric   else if ((SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t",
585*0fca6ea1SDimitry Andric                                                 MIRBuilder)) == nullptr)
586*0fca6ea1SDimitry Andric     report_fatal_error("Unable to recognize SPIRV type name: opencl.sampler_t");
587bdd1243dSDimitry Andric 
588bdd1243dSDimitry Andric   auto Sampler =
589bdd1243dSDimitry Andric       ResReg.isValid()
590bdd1243dSDimitry Andric           ? ResReg
591bdd1243dSDimitry Andric           : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
592bdd1243dSDimitry Andric   auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
593bdd1243dSDimitry Andric                  .addDef(Sampler)
594bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(SampTy))
595bdd1243dSDimitry Andric                  .addImm(AddrMode)
596bdd1243dSDimitry Andric                  .addImm(Param)
597bdd1243dSDimitry Andric                  .addImm(FilerMode);
598bdd1243dSDimitry Andric   assert(Res->getOperand(0).isReg());
599bdd1243dSDimitry Andric   return Res->getOperand(0).getReg();
600bdd1243dSDimitry Andric }
601bdd1243dSDimitry Andric 
60281ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildGlobalVariable(
60381ad6265SDimitry Andric     Register ResVReg, SPIRVType *BaseType, StringRef Name,
604bdd1243dSDimitry Andric     const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
60581ad6265SDimitry Andric     const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
606bdd1243dSDimitry Andric     SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
60781ad6265SDimitry Andric     bool IsInstSelector) {
60881ad6265SDimitry Andric   const GlobalVariable *GVar = nullptr;
60981ad6265SDimitry Andric   if (GV)
61081ad6265SDimitry Andric     GVar = cast<const GlobalVariable>(GV);
61181ad6265SDimitry Andric   else {
61281ad6265SDimitry Andric     // If GV is not passed explicitly, use the name to find or construct
61381ad6265SDimitry Andric     // the global variable.
61481ad6265SDimitry Andric     Module *M = MIRBuilder.getMF().getFunction().getParent();
61581ad6265SDimitry Andric     GVar = M->getGlobalVariable(Name);
61681ad6265SDimitry Andric     if (GVar == nullptr) {
61781ad6265SDimitry Andric       const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
618*0fca6ea1SDimitry Andric       // Module takes ownership of the global var.
61981ad6265SDimitry Andric       GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
62081ad6265SDimitry Andric                                 GlobalValue::ExternalLinkage, nullptr,
62181ad6265SDimitry Andric                                 Twine(Name));
62281ad6265SDimitry Andric     }
62381ad6265SDimitry Andric     GV = GVar;
62481ad6265SDimitry Andric   }
625fcaf7f86SDimitry Andric   Register Reg = DT.find(GVar, &MIRBuilder.getMF());
626fcaf7f86SDimitry Andric   if (Reg.isValid()) {
627fcaf7f86SDimitry Andric     if (Reg != ResVReg)
628fcaf7f86SDimitry Andric       MIRBuilder.buildCopy(ResVReg, Reg);
629fcaf7f86SDimitry Andric     return ResVReg;
630fcaf7f86SDimitry Andric   }
631fcaf7f86SDimitry Andric 
63281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
63381ad6265SDimitry Andric                  .addDef(ResVReg)
63481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
63581ad6265SDimitry Andric                  .addImm(static_cast<uint32_t>(Storage));
63681ad6265SDimitry Andric 
63781ad6265SDimitry Andric   if (Init != 0) {
63881ad6265SDimitry Andric     MIB.addUse(Init->getOperand(0).getReg());
63981ad6265SDimitry Andric   }
64081ad6265SDimitry Andric 
64181ad6265SDimitry Andric   // ISel may introduce a new register on this step, so we need to add it to
64281ad6265SDimitry Andric   // DT and correct its type avoiding fails on the next stage.
64381ad6265SDimitry Andric   if (IsInstSelector) {
64481ad6265SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
64581ad6265SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
64681ad6265SDimitry Andric                                      *Subtarget.getRegisterInfo(),
64781ad6265SDimitry Andric                                      *Subtarget.getRegBankInfo());
64881ad6265SDimitry Andric   }
64981ad6265SDimitry Andric   Reg = MIB->getOperand(0).getReg();
650753f127fSDimitry Andric   DT.add(GVar, &MIRBuilder.getMF(), Reg);
65181ad6265SDimitry Andric 
65281ad6265SDimitry Andric   // Set to Reg the same type as ResVReg has.
65381ad6265SDimitry Andric   auto MRI = MIRBuilder.getMRI();
65481ad6265SDimitry Andric   assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
65581ad6265SDimitry Andric   if (Reg != ResVReg) {
656*0fca6ea1SDimitry Andric     LLT RegLLTy =
657*0fca6ea1SDimitry Andric         LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());
65881ad6265SDimitry Andric     MRI->setType(Reg, RegLLTy);
65981ad6265SDimitry Andric     assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
660*0fca6ea1SDimitry Andric   } else {
661*0fca6ea1SDimitry Andric     // Our knowledge about the type may be updated.
662*0fca6ea1SDimitry Andric     // If that's the case, we need to update a type
663*0fca6ea1SDimitry Andric     // associated with the register.
664*0fca6ea1SDimitry Andric     SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);
665*0fca6ea1SDimitry Andric     if (!DefType || DefType != BaseType)
666*0fca6ea1SDimitry Andric       assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
66781ad6265SDimitry Andric   }
66881ad6265SDimitry Andric 
66981ad6265SDimitry Andric   // If it's a global variable with name, output OpName for it.
67081ad6265SDimitry Andric   if (GVar && GVar->hasName())
67181ad6265SDimitry Andric     buildOpName(Reg, GVar->getName(), MIRBuilder);
67281ad6265SDimitry Andric 
67381ad6265SDimitry Andric   // Output decorations for the GV.
67481ad6265SDimitry Andric   // TODO: maybe move to GenerateDecorations pass.
675*0fca6ea1SDimitry Andric   const SPIRVSubtarget &ST =
676*0fca6ea1SDimitry Andric       cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
677*0fca6ea1SDimitry Andric   if (IsConst && ST.isOpenCLEnv())
67881ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
67981ad6265SDimitry Andric 
680bdd1243dSDimitry Andric   if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
681bdd1243dSDimitry Andric     unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
682bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
683bdd1243dSDimitry Andric   }
68481ad6265SDimitry Andric 
68581ad6265SDimitry Andric   if (HasLinkageTy)
68681ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
68781ad6265SDimitry Andric                     {static_cast<uint32_t>(LinkageType)}, Name);
688bdd1243dSDimitry Andric 
689bdd1243dSDimitry Andric   SPIRV::BuiltIn::BuiltIn BuiltInId;
690bdd1243dSDimitry Andric   if (getSpirvBuiltInIdByName(Name, BuiltInId))
691bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
692bdd1243dSDimitry Andric                     {static_cast<uint32_t>(BuiltInId)});
693bdd1243dSDimitry Andric 
694*0fca6ea1SDimitry Andric   // If it's a global variable with "spirv.Decorations" metadata node
695*0fca6ea1SDimitry Andric   // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"
696*0fca6ea1SDimitry Andric   // arguments.
697*0fca6ea1SDimitry Andric   MDNode *GVarMD = nullptr;
698*0fca6ea1SDimitry Andric   if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)
699*0fca6ea1SDimitry Andric     buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD);
700*0fca6ea1SDimitry Andric 
70181ad6265SDimitry Andric   return Reg;
70281ad6265SDimitry Andric }
70381ad6265SDimitry Andric 
70481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
70581ad6265SDimitry Andric                                                SPIRVType *ElemType,
70681ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
70781ad6265SDimitry Andric                                                bool EmitIR) {
70881ad6265SDimitry Andric   assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
70981ad6265SDimitry Andric          "Invalid array element type");
71081ad6265SDimitry Andric   Register NumElementsVReg =
71181ad6265SDimitry Andric       buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
71281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
71381ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
71481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
71581ad6265SDimitry Andric                  .addUse(NumElementsVReg);
71681ad6265SDimitry Andric   return MIB;
71781ad6265SDimitry Andric }
71881ad6265SDimitry Andric 
719fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
720fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
721fcaf7f86SDimitry Andric   assert(Ty->hasName());
722fcaf7f86SDimitry Andric   const StringRef Name = Ty->hasName() ? Ty->getName() : "";
723fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
724fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
725fcaf7f86SDimitry Andric   addStringImm(Name, MIB);
726fcaf7f86SDimitry Andric   buildOpName(ResVReg, Name, MIRBuilder);
727fcaf7f86SDimitry Andric   return MIB;
728fcaf7f86SDimitry Andric }
729fcaf7f86SDimitry Andric 
730fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
731fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder,
732fcaf7f86SDimitry Andric                                                 bool EmitIR) {
733fcaf7f86SDimitry Andric   SmallVector<Register, 4> FieldTypes;
734fcaf7f86SDimitry Andric   for (const auto &Elem : Ty->elements()) {
735*0fca6ea1SDimitry Andric     SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder);
736fcaf7f86SDimitry Andric     assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
737fcaf7f86SDimitry Andric            "Invalid struct element type");
738fcaf7f86SDimitry Andric     FieldTypes.push_back(getSPIRVTypeID(ElemTy));
739fcaf7f86SDimitry Andric   }
740fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
741fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
742fcaf7f86SDimitry Andric   for (const auto &Ty : FieldTypes)
743fcaf7f86SDimitry Andric     MIB.addUse(Ty);
744fcaf7f86SDimitry Andric   if (Ty->hasName())
745fcaf7f86SDimitry Andric     buildOpName(ResVReg, Ty->getName(), MIRBuilder);
746fcaf7f86SDimitry Andric   if (Ty->isPacked())
747fcaf7f86SDimitry Andric     buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
748fcaf7f86SDimitry Andric   return MIB;
749fcaf7f86SDimitry Andric }
750fcaf7f86SDimitry Andric 
751bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
752bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
753bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual) {
75406c3fb27SDimitry Andric   assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
75506c3fb27SDimitry Andric   return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
756fcaf7f86SDimitry Andric }
757fcaf7f86SDimitry Andric 
758bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
759bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
760bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, Register Reg) {
761fcaf7f86SDimitry Andric   if (!Reg.isValid())
762fcaf7f86SDimitry Andric     Reg = createTypeVReg(MIRBuilder);
763fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
764fcaf7f86SDimitry Andric       .addDef(Reg)
76581ad6265SDimitry Andric       .addImm(static_cast<uint32_t>(SC))
76681ad6265SDimitry Andric       .addUse(getSPIRVTypeID(ElemType));
767fcaf7f86SDimitry Andric }
768fcaf7f86SDimitry Andric 
769bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
770bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
771fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
772fcaf7f86SDimitry Andric       .addUse(createTypeVReg(MIRBuilder))
773fcaf7f86SDimitry Andric       .addImm(static_cast<uint32_t>(SC));
77481ad6265SDimitry Andric }
77581ad6265SDimitry Andric 
77681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
77781ad6265SDimitry Andric     SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
77881ad6265SDimitry Andric     MachineIRBuilder &MIRBuilder) {
77981ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
78081ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
78181ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(RetType));
78281ad6265SDimitry Andric   for (const SPIRVType *ArgType : ArgTypes)
78381ad6265SDimitry Andric     MIB.addUse(getSPIRVTypeID(ArgType));
78481ad6265SDimitry Andric   return MIB;
78581ad6265SDimitry Andric }
78681ad6265SDimitry Andric 
787fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(
788fcaf7f86SDimitry Andric     const Type *Ty, SPIRVType *RetType,
789fcaf7f86SDimitry Andric     const SmallVectorImpl<SPIRVType *> &ArgTypes,
790fcaf7f86SDimitry Andric     MachineIRBuilder &MIRBuilder) {
791fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
792fcaf7f86SDimitry Andric   if (Reg.isValid())
793fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
794fcaf7f86SDimitry Andric   SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
7955f757f3fSDimitry Andric   DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
796fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(Ty, SpirvType);
797fcaf7f86SDimitry Andric }
798fcaf7f86SDimitry Andric 
799bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
800bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
801bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
802*0fca6ea1SDimitry Andric   Ty = adjustIntTypeByWidth(Ty);
803fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
804fcaf7f86SDimitry Andric   if (Reg.isValid())
805fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
806cb14a3feSDimitry Andric   if (ForwardPointerTypes.contains(Ty))
807fcaf7f86SDimitry Andric     return ForwardPointerTypes[Ty];
808fcaf7f86SDimitry Andric   return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
809fcaf7f86SDimitry Andric }
810fcaf7f86SDimitry Andric 
811fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getSPIRVTypeID(const SPIRVType *SpirvType) const {
812fcaf7f86SDimitry Andric   assert(SpirvType && "Attempting to get type id for nullptr type.");
813fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
814fcaf7f86SDimitry Andric     return SpirvType->uses().begin()->getReg();
815fcaf7f86SDimitry Andric   return SpirvType->defs().begin()->getReg();
816fcaf7f86SDimitry Andric }
817fcaf7f86SDimitry Andric 
818*0fca6ea1SDimitry Andric // We need to use a new LLVM integer type if there is a mismatch between
819*0fca6ea1SDimitry Andric // number of bits in LLVM and SPIRV integer types to let DuplicateTracker
820*0fca6ea1SDimitry Andric // ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without
821*0fca6ea1SDimitry Andric // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the
822*0fca6ea1SDimitry Andric // same "OpTypeInt 8" type for a series of LLVM integer types with number of
823*0fca6ea1SDimitry Andric // bits less than 8. This would lead to duplicate type definitions
824*0fca6ea1SDimitry Andric // eventually due to the method that DuplicateTracker utilizes to reason
825*0fca6ea1SDimitry Andric // about uniqueness of type records.
826*0fca6ea1SDimitry Andric const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {
827*0fca6ea1SDimitry Andric   if (auto IType = dyn_cast<IntegerType>(Ty)) {
828*0fca6ea1SDimitry Andric     unsigned SrcBitWidth = IType->getBitWidth();
829*0fca6ea1SDimitry Andric     if (SrcBitWidth > 1) {
830*0fca6ea1SDimitry Andric       unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);
831*0fca6ea1SDimitry Andric       // Maybe change source LLVM type to keep DuplicateTracker consistent.
832*0fca6ea1SDimitry Andric       if (SrcBitWidth != BitWidth)
833*0fca6ea1SDimitry Andric         Ty = IntegerType::get(Ty->getContext(), BitWidth);
834*0fca6ea1SDimitry Andric     }
835*0fca6ea1SDimitry Andric   }
836*0fca6ea1SDimitry Andric   return Ty;
837*0fca6ea1SDimitry Andric }
838*0fca6ea1SDimitry Andric 
839bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
840bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
841bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
842bdd1243dSDimitry Andric   if (isSpecialOpaqueType(Ty))
843bdd1243dSDimitry Andric     return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
844fcaf7f86SDimitry Andric   auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
845fcaf7f86SDimitry Andric   auto t = TypeToSPIRVTypeMap.find(Ty);
846fcaf7f86SDimitry Andric   if (t != TypeToSPIRVTypeMap.end()) {
847fcaf7f86SDimitry Andric     auto tt = t->second.find(&MIRBuilder.getMF());
848fcaf7f86SDimitry Andric     if (tt != t->second.end())
849fcaf7f86SDimitry Andric       return getSPIRVTypeForVReg(tt->second);
850fcaf7f86SDimitry Andric   }
851fcaf7f86SDimitry Andric 
85281ad6265SDimitry Andric   if (auto IType = dyn_cast<IntegerType>(Ty)) {
85381ad6265SDimitry Andric     const unsigned Width = IType->getBitWidth();
85481ad6265SDimitry Andric     return Width == 1 ? getOpTypeBool(MIRBuilder)
85581ad6265SDimitry Andric                       : getOpTypeInt(Width, MIRBuilder, false);
85681ad6265SDimitry Andric   }
85781ad6265SDimitry Andric   if (Ty->isFloatingPointTy())
85881ad6265SDimitry Andric     return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
85981ad6265SDimitry Andric   if (Ty->isVoidTy())
86081ad6265SDimitry Andric     return getOpTypeVoid(MIRBuilder);
86181ad6265SDimitry Andric   if (Ty->isVectorTy()) {
862fcaf7f86SDimitry Andric     SPIRVType *El =
863fcaf7f86SDimitry Andric         findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
86481ad6265SDimitry Andric     return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
86581ad6265SDimitry Andric                            MIRBuilder);
86681ad6265SDimitry Andric   }
86781ad6265SDimitry Andric   if (Ty->isArrayTy()) {
868fcaf7f86SDimitry Andric     SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
86981ad6265SDimitry Andric     return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
87081ad6265SDimitry Andric   }
871fcaf7f86SDimitry Andric   if (auto SType = dyn_cast<StructType>(Ty)) {
872fcaf7f86SDimitry Andric     if (SType->isOpaque())
873fcaf7f86SDimitry Andric       return getOpTypeOpaque(SType, MIRBuilder);
874fcaf7f86SDimitry Andric     return getOpTypeStruct(SType, MIRBuilder, EmitIR);
875fcaf7f86SDimitry Andric   }
87681ad6265SDimitry Andric   if (auto FType = dyn_cast<FunctionType>(Ty)) {
877fcaf7f86SDimitry Andric     SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
87881ad6265SDimitry Andric     SmallVector<SPIRVType *, 4> ParamTypes;
87981ad6265SDimitry Andric     for (const auto &t : FType->params()) {
880fcaf7f86SDimitry Andric       ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
88181ad6265SDimitry Andric     }
88281ad6265SDimitry Andric     return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
88381ad6265SDimitry Andric   }
884*0fca6ea1SDimitry Andric   unsigned AddrSpace = 0xFFFF;
885*0fca6ea1SDimitry Andric   if (auto PType = dyn_cast<TypedPointerType>(Ty))
886*0fca6ea1SDimitry Andric     AddrSpace = PType->getAddressSpace();
887*0fca6ea1SDimitry Andric   else if (auto PType = dyn_cast<PointerType>(Ty))
888*0fca6ea1SDimitry Andric     AddrSpace = PType->getAddressSpace();
889*0fca6ea1SDimitry Andric   else
890*0fca6ea1SDimitry Andric     report_fatal_error("Unable to convert LLVM type to SPIRVType", true);
891*0fca6ea1SDimitry Andric 
892*0fca6ea1SDimitry Andric   SPIRVType *SpvElementType = nullptr;
893*0fca6ea1SDimitry Andric   if (auto PType = dyn_cast<TypedPointerType>(Ty))
894*0fca6ea1SDimitry Andric     SpvElementType = getOrCreateSPIRVType(PType->getElementType(), MIRBuilder,
895*0fca6ea1SDimitry Andric                                           AccQual, EmitIR);
896*0fca6ea1SDimitry Andric   else
89781ad6265SDimitry Andric     SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
898*0fca6ea1SDimitry Andric 
899*0fca6ea1SDimitry Andric   // Get access to information about available extensions
900*0fca6ea1SDimitry Andric   const SPIRVSubtarget *ST =
901*0fca6ea1SDimitry Andric       static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
902*0fca6ea1SDimitry Andric   auto SC = addressSpaceToStorageClass(AddrSpace, *ST);
903fcaf7f86SDimitry Andric   // Null pointer means we have a loop in type definitions, make and
904fcaf7f86SDimitry Andric   // return corresponding OpTypeForwardPointer.
905fcaf7f86SDimitry Andric   if (SpvElementType == nullptr) {
906cb14a3feSDimitry Andric     if (!ForwardPointerTypes.contains(Ty))
907*0fca6ea1SDimitry Andric       ForwardPointerTypes[Ty] = getOpTypeForwardPointer(SC, MIRBuilder);
908*0fca6ea1SDimitry Andric     return ForwardPointerTypes[Ty];
909fcaf7f86SDimitry Andric   }
910fcaf7f86SDimitry Andric   // If we have forward pointer associated with this type, use its register
911fcaf7f86SDimitry Andric   // operand to create OpTypePointer.
912*0fca6ea1SDimitry Andric   if (ForwardPointerTypes.contains(Ty)) {
913*0fca6ea1SDimitry Andric     Register Reg = getSPIRVTypeID(ForwardPointerTypes[Ty]);
914fcaf7f86SDimitry Andric     return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
91581ad6265SDimitry Andric   }
916*0fca6ea1SDimitry Andric 
917*0fca6ea1SDimitry Andric   return getOrCreateSPIRVPointerType(SpvElementType, MIRBuilder, SC);
91881ad6265SDimitry Andric }
91981ad6265SDimitry Andric 
920fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
921fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
922bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
923*0fca6ea1SDimitry Andric   if (TypesInProcessing.count(Ty) && !isPointerTy(Ty))
924fcaf7f86SDimitry Andric     return nullptr;
925fcaf7f86SDimitry Andric   TypesInProcessing.insert(Ty);
926fcaf7f86SDimitry Andric   SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
927fcaf7f86SDimitry Andric   TypesInProcessing.erase(Ty);
928fcaf7f86SDimitry Andric   VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
929*0fca6ea1SDimitry Andric   SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);
930fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
931fcaf7f86SDimitry Andric   // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
932fcaf7f86SDimitry Andric   // will be added later. For special types it is already added to DT.
933fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
9345f757f3fSDimitry Andric       !isSpecialOpaqueType(Ty)) {
935*0fca6ea1SDimitry Andric     if (!isPointerTy(Ty))
936fcaf7f86SDimitry Andric       DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
937*0fca6ea1SDimitry Andric     else if (isTypedPointerTy(Ty))
938*0fca6ea1SDimitry Andric       DT.add(cast<TypedPointerType>(Ty)->getElementType(),
939*0fca6ea1SDimitry Andric              getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
940*0fca6ea1SDimitry Andric              getSPIRVTypeID(SpirvType));
9415f757f3fSDimitry Andric     else
9425f757f3fSDimitry Andric       DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
943*0fca6ea1SDimitry Andric              getPointerAddressSpace(Ty), &MIRBuilder.getMF(),
9445f757f3fSDimitry Andric              getSPIRVTypeID(SpirvType));
9455f757f3fSDimitry Andric   }
946fcaf7f86SDimitry Andric 
947fcaf7f86SDimitry Andric   return SpirvType;
948fcaf7f86SDimitry Andric }
949fcaf7f86SDimitry Andric 
950*0fca6ea1SDimitry Andric SPIRVType *
951*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg,
952*0fca6ea1SDimitry Andric                                          const MachineFunction *MF) const {
953*0fca6ea1SDimitry Andric   auto t = VRegToTypeMap.find(MF ? MF : CurMF);
95481ad6265SDimitry Andric   if (t != VRegToTypeMap.end()) {
95581ad6265SDimitry Andric     auto tt = t->second.find(VReg);
95681ad6265SDimitry Andric     if (tt != t->second.end())
95781ad6265SDimitry Andric       return tt->second;
95881ad6265SDimitry Andric   }
95981ad6265SDimitry Andric   return nullptr;
96081ad6265SDimitry Andric }
96181ad6265SDimitry Andric 
96281ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
963fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
964bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
9655f757f3fSDimitry Andric   Register Reg;
966*0fca6ea1SDimitry Andric   if (!isPointerTy(Ty)) {
967*0fca6ea1SDimitry Andric     Ty = adjustIntTypeByWidth(Ty);
9685f757f3fSDimitry Andric     Reg = DT.find(Ty, &MIRBuilder.getMF());
969*0fca6ea1SDimitry Andric   } else if (isTypedPointerTy(Ty)) {
970*0fca6ea1SDimitry Andric     Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(),
971*0fca6ea1SDimitry Andric                   getPointerAddressSpace(Ty), &MIRBuilder.getMF());
972*0fca6ea1SDimitry Andric   } else {
9735f757f3fSDimitry Andric     Reg =
9745f757f3fSDimitry Andric         DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
975*0fca6ea1SDimitry Andric                 getPointerAddressSpace(Ty), &MIRBuilder.getMF());
976*0fca6ea1SDimitry Andric   }
9775f757f3fSDimitry Andric 
978bdd1243dSDimitry Andric   if (Reg.isValid() && !isSpecialOpaqueType(Ty))
979753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
980fcaf7f86SDimitry Andric   TypesInProcessing.clear();
981fcaf7f86SDimitry Andric   SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
982fcaf7f86SDimitry Andric   // Create normal pointer types for the corresponding OpTypeForwardPointers.
983fcaf7f86SDimitry Andric   for (auto &CU : ForwardPointerTypes) {
984fcaf7f86SDimitry Andric     const Type *Ty2 = CU.first;
985fcaf7f86SDimitry Andric     SPIRVType *STy2 = CU.second;
986fcaf7f86SDimitry Andric     if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
987fcaf7f86SDimitry Andric       STy2 = getSPIRVTypeForVReg(Reg);
988fcaf7f86SDimitry Andric     else
989fcaf7f86SDimitry Andric       STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
990fcaf7f86SDimitry Andric     if (Ty == Ty2)
991fcaf7f86SDimitry Andric       STy = STy2;
992fcaf7f86SDimitry Andric   }
993fcaf7f86SDimitry Andric   ForwardPointerTypes.clear();
994fcaf7f86SDimitry Andric   return STy;
99581ad6265SDimitry Andric }
99681ad6265SDimitry Andric 
99781ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOfType(Register VReg,
99881ad6265SDimitry Andric                                          unsigned TypeOpcode) const {
99981ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
100081ad6265SDimitry Andric   assert(Type && "isScalarOfType VReg has no type assigned");
100181ad6265SDimitry Andric   return Type->getOpcode() == TypeOpcode;
100281ad6265SDimitry Andric }
100381ad6265SDimitry Andric 
100481ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg,
100581ad6265SDimitry Andric                                                  unsigned TypeOpcode) const {
100681ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
100781ad6265SDimitry Andric   assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
100881ad6265SDimitry Andric   if (Type->getOpcode() == TypeOpcode)
100981ad6265SDimitry Andric     return true;
101081ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
101181ad6265SDimitry Andric     Register ScalarTypeVReg = Type->getOperand(1).getReg();
101281ad6265SDimitry Andric     SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
101381ad6265SDimitry Andric     return ScalarType->getOpcode() == TypeOpcode;
101481ad6265SDimitry Andric   }
101581ad6265SDimitry Andric   return false;
101681ad6265SDimitry Andric }
101781ad6265SDimitry Andric 
101881ad6265SDimitry Andric unsigned
1019*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorComponentCount(Register VReg) const {
1020*0fca6ea1SDimitry Andric   return getScalarOrVectorComponentCount(getSPIRVTypeForVReg(VReg));
1021*0fca6ea1SDimitry Andric }
1022*0fca6ea1SDimitry Andric 
1023*0fca6ea1SDimitry Andric unsigned
1024*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorComponentCount(SPIRVType *Type) const {
1025*0fca6ea1SDimitry Andric   if (!Type)
1026*0fca6ea1SDimitry Andric     return 0;
1027*0fca6ea1SDimitry Andric   return Type->getOpcode() == SPIRV::OpTypeVector
1028*0fca6ea1SDimitry Andric              ? static_cast<unsigned>(Type->getOperand(2).getImm())
1029*0fca6ea1SDimitry Andric              : 1;
1030*0fca6ea1SDimitry Andric }
1031*0fca6ea1SDimitry Andric 
1032*0fca6ea1SDimitry Andric unsigned
103381ad6265SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorBitWidth(const SPIRVType *Type) const {
103481ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
103581ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
103681ad6265SDimitry Andric     auto EleTypeReg = Type->getOperand(1).getReg();
103781ad6265SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
103881ad6265SDimitry Andric   }
103981ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeInt ||
104081ad6265SDimitry Andric       Type->getOpcode() == SPIRV::OpTypeFloat)
104181ad6265SDimitry Andric     return Type->getOperand(1).getImm();
104281ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeBool)
104381ad6265SDimitry Andric     return 1;
104481ad6265SDimitry Andric   llvm_unreachable("Attempting to get bit width of non-integer/float type.");
104581ad6265SDimitry Andric }
104681ad6265SDimitry Andric 
1047*0fca6ea1SDimitry Andric unsigned SPIRVGlobalRegistry::getNumScalarOrVectorTotalBitWidth(
1048*0fca6ea1SDimitry Andric     const SPIRVType *Type) const {
104981ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
1050*0fca6ea1SDimitry Andric   unsigned NumElements = 1;
105181ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
1052*0fca6ea1SDimitry Andric     NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());
1053*0fca6ea1SDimitry Andric     Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
105481ad6265SDimitry Andric   }
1055*0fca6ea1SDimitry Andric   return Type->getOpcode() == SPIRV::OpTypeInt ||
1056*0fca6ea1SDimitry Andric                  Type->getOpcode() == SPIRV::OpTypeFloat
1057*0fca6ea1SDimitry Andric              ? NumElements * Type->getOperand(1).getImm()
1058*0fca6ea1SDimitry Andric              : 0;
1059*0fca6ea1SDimitry Andric }
1060*0fca6ea1SDimitry Andric 
1061*0fca6ea1SDimitry Andric const SPIRVType *SPIRVGlobalRegistry::retrieveScalarOrVectorIntType(
1062*0fca6ea1SDimitry Andric     const SPIRVType *Type) const {
1063*0fca6ea1SDimitry Andric   if (Type && Type->getOpcode() == SPIRV::OpTypeVector)
1064*0fca6ea1SDimitry Andric     Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());
1065*0fca6ea1SDimitry Andric   return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;
1066*0fca6ea1SDimitry Andric }
1067*0fca6ea1SDimitry Andric 
1068*0fca6ea1SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorSigned(const SPIRVType *Type) const {
1069*0fca6ea1SDimitry Andric   const SPIRVType *IntType = retrieveScalarOrVectorIntType(Type);
1070*0fca6ea1SDimitry Andric   return IntType && IntType->getOperand(2).getImm() != 0;
1071*0fca6ea1SDimitry Andric }
1072*0fca6ea1SDimitry Andric 
1073*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getPointeeType(SPIRVType *PtrType) {
1074*0fca6ea1SDimitry Andric   return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer
1075*0fca6ea1SDimitry Andric              ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())
1076*0fca6ea1SDimitry Andric              : nullptr;
1077*0fca6ea1SDimitry Andric }
1078*0fca6ea1SDimitry Andric 
1079*0fca6ea1SDimitry Andric unsigned SPIRVGlobalRegistry::getPointeeTypeOp(Register PtrReg) {
1080*0fca6ea1SDimitry Andric   SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));
1081*0fca6ea1SDimitry Andric   return ElemType ? ElemType->getOpcode() : 0;
1082*0fca6ea1SDimitry Andric }
1083*0fca6ea1SDimitry Andric 
1084*0fca6ea1SDimitry Andric bool SPIRVGlobalRegistry::isBitcastCompatible(const SPIRVType *Type1,
1085*0fca6ea1SDimitry Andric                                               const SPIRVType *Type2) const {
1086*0fca6ea1SDimitry Andric   if (!Type1 || !Type2)
1087*0fca6ea1SDimitry Andric     return false;
1088*0fca6ea1SDimitry Andric   auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();
1089*0fca6ea1SDimitry Andric   // Ignore difference between <1.5 and >=1.5 protocol versions:
1090*0fca6ea1SDimitry Andric   // it's valid if either Result Type or Operand is a pointer, and the other
1091*0fca6ea1SDimitry Andric   // is a pointer, an integer scalar, or an integer vector.
1092*0fca6ea1SDimitry Andric   if (Op1 == SPIRV::OpTypePointer &&
1093*0fca6ea1SDimitry Andric       (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))
1094*0fca6ea1SDimitry Andric     return true;
1095*0fca6ea1SDimitry Andric   if (Op2 == SPIRV::OpTypePointer &&
1096*0fca6ea1SDimitry Andric       (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))
1097*0fca6ea1SDimitry Andric     return true;
1098*0fca6ea1SDimitry Andric   unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),
1099*0fca6ea1SDimitry Andric            Bits2 = getNumScalarOrVectorTotalBitWidth(Type2);
1100*0fca6ea1SDimitry Andric   return Bits1 > 0 && Bits1 == Bits2;
110181ad6265SDimitry Andric }
110281ad6265SDimitry Andric 
1103bdd1243dSDimitry Andric SPIRV::StorageClass::StorageClass
110481ad6265SDimitry Andric SPIRVGlobalRegistry::getPointerStorageClass(Register VReg) const {
110581ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
110681ad6265SDimitry Andric   assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
110781ad6265SDimitry Andric          Type->getOperand(1).isImm() && "Pointer type is expected");
1108bdd1243dSDimitry Andric   return static_cast<SPIRV::StorageClass::StorageClass>(
1109bdd1243dSDimitry Andric       Type->getOperand(1).getImm());
1110bdd1243dSDimitry Andric }
1111bdd1243dSDimitry Andric 
1112bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
1113bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
1114bdd1243dSDimitry Andric     uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
1115bdd1243dSDimitry Andric     SPIRV::ImageFormat::ImageFormat ImageFormat,
1116bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1117*0fca6ea1SDimitry Andric   auto TD = SPIRV::make_descr_image(SPIRVToLLVMType.lookup(SampledType), Dim,
1118*0fca6ea1SDimitry Andric                                     Depth, Arrayed, Multisampled, Sampled,
1119*0fca6ea1SDimitry Andric                                     ImageFormat, AccessQual);
1120bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1121bdd1243dSDimitry Andric     return Res;
1122bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
1123bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1124bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
1125bdd1243dSDimitry Andric       .addDef(ResVReg)
1126bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(SampledType))
1127bdd1243dSDimitry Andric       .addImm(Dim)
1128bdd1243dSDimitry Andric       .addImm(Depth)        // Depth (whether or not it is a Depth image).
1129bdd1243dSDimitry Andric       .addImm(Arrayed)      // Arrayed.
1130bdd1243dSDimitry Andric       .addImm(Multisampled) // Multisampled (0 = only single-sample).
1131bdd1243dSDimitry Andric       .addImm(Sampled)      // Sampled (0 = usage known at runtime).
1132bdd1243dSDimitry Andric       .addImm(ImageFormat)
1133bdd1243dSDimitry Andric       .addImm(AccessQual);
1134bdd1243dSDimitry Andric }
1135bdd1243dSDimitry Andric 
1136bdd1243dSDimitry Andric SPIRVType *
1137bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
1138*0fca6ea1SDimitry Andric   auto TD = SPIRV::make_descr_sampler();
1139bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1140bdd1243dSDimitry Andric     return Res;
1141bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
1142bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1143bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
1144bdd1243dSDimitry Andric }
1145bdd1243dSDimitry Andric 
1146bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
1147bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder,
1148bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
1149*0fca6ea1SDimitry Andric   auto TD = SPIRV::make_descr_pipe(AccessQual);
1150bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1151bdd1243dSDimitry Andric     return Res;
1152bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
1153bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1154bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
1155bdd1243dSDimitry Andric       .addDef(ResVReg)
1156bdd1243dSDimitry Andric       .addImm(AccessQual);
1157bdd1243dSDimitry Andric }
1158bdd1243dSDimitry Andric 
1159bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
1160bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder) {
1161*0fca6ea1SDimitry Andric   auto TD = SPIRV::make_descr_event();
1162bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1163bdd1243dSDimitry Andric     return Res;
1164bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
1165bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1166bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
1167bdd1243dSDimitry Andric }
1168bdd1243dSDimitry Andric 
1169bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(
1170bdd1243dSDimitry Andric     SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
1171*0fca6ea1SDimitry Andric   auto TD = SPIRV::make_descr_sampled_image(
1172bdd1243dSDimitry Andric       SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
1173bdd1243dSDimitry Andric           ImageType->getOperand(1).getReg())),
1174bdd1243dSDimitry Andric       ImageType);
1175bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
1176bdd1243dSDimitry Andric     return Res;
1177bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
1178bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
1179bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
1180bdd1243dSDimitry Andric       .addDef(ResVReg)
1181bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(ImageType));
1182bdd1243dSDimitry Andric }
1183bdd1243dSDimitry Andric 
1184*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeCoopMatr(
1185*0fca6ea1SDimitry Andric     MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,
1186*0fca6ea1SDimitry Andric     const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,
1187*0fca6ea1SDimitry Andric     uint32_t Use) {
1188*0fca6ea1SDimitry Andric   Register ResVReg = DT.find(ExtensionType, &MIRBuilder.getMF());
1189*0fca6ea1SDimitry Andric   if (ResVReg.isValid())
1190*0fca6ea1SDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1191*0fca6ea1SDimitry Andric   ResVReg = createTypeVReg(MIRBuilder);
1192*0fca6ea1SDimitry Andric   SPIRVType *SpirvTy =
1193*0fca6ea1SDimitry Andric       MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)
1194*0fca6ea1SDimitry Andric           .addDef(ResVReg)
1195*0fca6ea1SDimitry Andric           .addUse(getSPIRVTypeID(ElemType))
1196*0fca6ea1SDimitry Andric           .addUse(buildConstantInt(Scope, MIRBuilder, nullptr, true))
1197*0fca6ea1SDimitry Andric           .addUse(buildConstantInt(Rows, MIRBuilder, nullptr, true))
1198*0fca6ea1SDimitry Andric           .addUse(buildConstantInt(Columns, MIRBuilder, nullptr, true))
1199*0fca6ea1SDimitry Andric           .addUse(buildConstantInt(Use, MIRBuilder, nullptr, true));
1200*0fca6ea1SDimitry Andric   DT.add(ExtensionType, &MIRBuilder.getMF(), ResVReg);
1201*0fca6ea1SDimitry Andric   return SpirvTy;
1202*0fca6ea1SDimitry Andric }
1203*0fca6ea1SDimitry Andric 
1204bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(
1205bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
1206bdd1243dSDimitry Andric   Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
1207bdd1243dSDimitry Andric   if (ResVReg.isValid())
1208bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
1209bdd1243dSDimitry Andric   ResVReg = createTypeVReg(MIRBuilder);
12105f757f3fSDimitry Andric   SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
1211bdd1243dSDimitry Andric   DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
12125f757f3fSDimitry Andric   return SpirvTy;
1213bdd1243dSDimitry Andric }
1214bdd1243dSDimitry Andric 
1215bdd1243dSDimitry Andric const MachineInstr *
1216bdd1243dSDimitry Andric SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
1217bdd1243dSDimitry Andric                                        MachineIRBuilder &MIRBuilder) {
1218bdd1243dSDimitry Andric   Register Reg = DT.find(TD, &MIRBuilder.getMF());
1219bdd1243dSDimitry Andric   if (Reg.isValid())
1220bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
1221bdd1243dSDimitry Andric   return nullptr;
1222bdd1243dSDimitry Andric }
1223bdd1243dSDimitry Andric 
1224*0fca6ea1SDimitry Andric // Returns nullptr if unable to recognize SPIRV type name
12255f757f3fSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(
12265f757f3fSDimitry Andric     StringRef TypeStr, MachineIRBuilder &MIRBuilder,
12275f757f3fSDimitry Andric     SPIRV::StorageClass::StorageClass SC,
12285f757f3fSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AQ) {
1229bdd1243dSDimitry Andric   unsigned VecElts = 0;
1230bdd1243dSDimitry Andric   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
1231bdd1243dSDimitry Andric 
12325f757f3fSDimitry Andric   // Parse strings representing either a SPIR-V or OpenCL builtin type.
12335f757f3fSDimitry Andric   if (hasBuiltinTypePrefix(TypeStr))
1234*0fca6ea1SDimitry Andric     return getOrCreateSPIRVType(SPIRV::parseBuiltinTypeNameToTargetExtType(
1235*0fca6ea1SDimitry Andric                                     TypeStr.str(), MIRBuilder.getContext()),
12365f757f3fSDimitry Andric                                 MIRBuilder, AQ);
12375f757f3fSDimitry Andric 
1238bdd1243dSDimitry Andric   // Parse type name in either "typeN" or "type vector[N]" format, where
1239bdd1243dSDimitry Andric   // N is the number of elements of the vector.
12405f757f3fSDimitry Andric   Type *Ty;
12415f757f3fSDimitry Andric 
1242*0fca6ea1SDimitry Andric   Ty = parseBasicTypeName(TypeStr, Ctx);
1243*0fca6ea1SDimitry Andric   if (!Ty)
1244*0fca6ea1SDimitry Andric     // Unable to recognize SPIRV type name
1245*0fca6ea1SDimitry Andric     return nullptr;
12465f757f3fSDimitry Andric 
12475f757f3fSDimitry Andric   auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
12485f757f3fSDimitry Andric 
12495f757f3fSDimitry Andric   // Handle "type*" or  "type* vector[N]".
12505f757f3fSDimitry Andric   if (TypeStr.starts_with("*")) {
12515f757f3fSDimitry Andric     SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
12525f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("*"));
12535f757f3fSDimitry Andric   }
12545f757f3fSDimitry Andric 
12555f757f3fSDimitry Andric   // Handle "typeN*" or  "type vector[N]*".
12565f757f3fSDimitry Andric   bool IsPtrToVec = TypeStr.consume_back("*");
12575f757f3fSDimitry Andric 
1258647cbc5dSDimitry Andric   if (TypeStr.consume_front(" vector[")) {
1259bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1260bdd1243dSDimitry Andric   }
1261bdd1243dSDimitry Andric   TypeStr.getAsInteger(10, VecElts);
1262bdd1243dSDimitry Andric   if (VecElts > 0)
1263bdd1243dSDimitry Andric     SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
12645f757f3fSDimitry Andric 
12655f757f3fSDimitry Andric   if (IsPtrToVec)
12665f757f3fSDimitry Andric     SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
12675f757f3fSDimitry Andric 
1268bdd1243dSDimitry Andric   return SpirvTy;
126981ad6265SDimitry Andric }
127081ad6265SDimitry Andric 
127181ad6265SDimitry Andric SPIRVType *
127281ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(unsigned BitWidth,
127381ad6265SDimitry Andric                                                  MachineIRBuilder &MIRBuilder) {
127481ad6265SDimitry Andric   return getOrCreateSPIRVType(
127581ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), BitWidth),
127681ad6265SDimitry Andric       MIRBuilder);
127781ad6265SDimitry Andric }
127881ad6265SDimitry Andric 
1279fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1280753f127fSDimitry Andric                                                         SPIRVType *SpirvType) {
1281753f127fSDimitry Andric   assert(CurMF == SpirvType->getMF());
128281ad6265SDimitry Andric   VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
1283*0fca6ea1SDimitry Andric   SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);
128481ad6265SDimitry Andric   return SpirvType;
128581ad6265SDimitry Andric }
128681ad6265SDimitry Andric 
1287*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,
1288*0fca6ea1SDimitry Andric                                                      MachineInstr &I,
1289*0fca6ea1SDimitry Andric                                                      const SPIRVInstrInfo &TII,
1290*0fca6ea1SDimitry Andric                                                      unsigned SPIRVOPcode,
1291*0fca6ea1SDimitry Andric                                                      Type *LLVMTy) {
1292753f127fSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1293753f127fSDimitry Andric   if (Reg.isValid())
1294753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
129581ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1296*0fca6ea1SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRVOPcode))
129781ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
129881ad6265SDimitry Andric                  .addImm(BitWidth)
129981ad6265SDimitry Andric                  .addImm(0);
13005f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1301fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
130281ad6265SDimitry Andric }
130381ad6265SDimitry Andric 
1304*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(
1305*0fca6ea1SDimitry Andric     unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1306*0fca6ea1SDimitry Andric   // Maybe adjust bit width to keep DuplicateTracker consistent. Without
1307*0fca6ea1SDimitry Andric   // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for
1308*0fca6ea1SDimitry Andric   // example, the same "OpTypeInt 8" type for a series of LLVM integer types
1309*0fca6ea1SDimitry Andric   // with number of bits less than 8, causing duplicate type definitions.
1310*0fca6ea1SDimitry Andric   BitWidth = adjustOpTypeIntWidth(BitWidth);
1311*0fca6ea1SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);
1312*0fca6ea1SDimitry Andric   return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);
1313*0fca6ea1SDimitry Andric }
1314*0fca6ea1SDimitry Andric 
1315*0fca6ea1SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVFloatType(
1316*0fca6ea1SDimitry Andric     unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
1317*0fca6ea1SDimitry Andric   LLVMContext &Ctx = CurMF->getFunction().getContext();
1318*0fca6ea1SDimitry Andric   Type *LLVMTy;
1319*0fca6ea1SDimitry Andric   switch (BitWidth) {
1320*0fca6ea1SDimitry Andric   case 16:
1321*0fca6ea1SDimitry Andric     LLVMTy = Type::getHalfTy(Ctx);
1322*0fca6ea1SDimitry Andric     break;
1323*0fca6ea1SDimitry Andric   case 32:
1324*0fca6ea1SDimitry Andric     LLVMTy = Type::getFloatTy(Ctx);
1325*0fca6ea1SDimitry Andric     break;
1326*0fca6ea1SDimitry Andric   case 64:
1327*0fca6ea1SDimitry Andric     LLVMTy = Type::getDoubleTy(Ctx);
1328*0fca6ea1SDimitry Andric     break;
1329*0fca6ea1SDimitry Andric   default:
1330*0fca6ea1SDimitry Andric     llvm_unreachable("Bit width is of unexpected size.");
1331*0fca6ea1SDimitry Andric   }
1332*0fca6ea1SDimitry Andric   return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);
1333*0fca6ea1SDimitry Andric }
1334*0fca6ea1SDimitry Andric 
133581ad6265SDimitry Andric SPIRVType *
133681ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder) {
133781ad6265SDimitry Andric   return getOrCreateSPIRVType(
133881ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
133981ad6265SDimitry Andric       MIRBuilder);
134081ad6265SDimitry Andric }
134181ad6265SDimitry Andric 
1342fcaf7f86SDimitry Andric SPIRVType *
1343fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
1344fcaf7f86SDimitry Andric                                               const SPIRVInstrInfo &TII) {
1345fcaf7f86SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), 1);
1346fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1347fcaf7f86SDimitry Andric   if (Reg.isValid())
1348fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
1349fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1350fcaf7f86SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1351fcaf7f86SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()));
13525f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1353fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1354fcaf7f86SDimitry Andric }
1355fcaf7f86SDimitry Andric 
135681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
135781ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
135881ad6265SDimitry Andric   return getOrCreateSPIRVType(
135981ad6265SDimitry Andric       FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
136081ad6265SDimitry Andric                            NumElements),
136181ad6265SDimitry Andric       MIRBuilder);
136281ad6265SDimitry Andric }
136381ad6265SDimitry Andric 
136481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
136581ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
136681ad6265SDimitry Andric     const SPIRVInstrInfo &TII) {
136781ad6265SDimitry Andric   Type *LLVMTy = FixedVectorType::get(
136881ad6265SDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1369fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1370fcaf7f86SDimitry Andric   if (Reg.isValid())
1371fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
137281ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
137381ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
137481ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
137581ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
137681ad6265SDimitry Andric                  .addImm(NumElements);
13775f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1378fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
137981ad6265SDimitry Andric }
138081ad6265SDimitry Andric 
1381bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
1382bdd1243dSDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1383bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII) {
1384bdd1243dSDimitry Andric   Type *LLVMTy = ArrayType::get(
1385bdd1243dSDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1386bdd1243dSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1387bdd1243dSDimitry Andric   if (Reg.isValid())
1388bdd1243dSDimitry Andric     return getSPIRVTypeForVReg(Reg);
1389bdd1243dSDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1390bdd1243dSDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1391bdd1243dSDimitry Andric   Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1392bdd1243dSDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1393bdd1243dSDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
1394bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
1395bdd1243dSDimitry Andric                  .addUse(Len);
13965f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1397bdd1243dSDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1398bdd1243dSDimitry Andric }
1399bdd1243dSDimitry Andric 
1400bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
1401bdd1243dSDimitry Andric     SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
14025f757f3fSDimitry Andric     SPIRV::StorageClass::StorageClass SC) {
14035f757f3fSDimitry Andric   const Type *PointerElementType = getTypeForSPIRVType(BaseType);
14045f757f3fSDimitry Andric   unsigned AddressSpace = storageClassToAddressSpace(SC);
1405*0fca6ea1SDimitry Andric   Type *LLVMTy = TypedPointerType::get(const_cast<Type *>(PointerElementType),
1406*0fca6ea1SDimitry Andric                                        AddressSpace);
1407*0fca6ea1SDimitry Andric   // check if this type is already available
14085f757f3fSDimitry Andric   Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
14095f757f3fSDimitry Andric   if (Reg.isValid())
14105f757f3fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
1411*0fca6ea1SDimitry Andric   // create a new type
14125f757f3fSDimitry Andric   auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
14135f757f3fSDimitry Andric                      MIRBuilder.getDebugLoc(),
14145f757f3fSDimitry Andric                      MIRBuilder.getTII().get(SPIRV::OpTypePointer))
14155f757f3fSDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
14165f757f3fSDimitry Andric                  .addImm(static_cast<uint32_t>(SC))
14175f757f3fSDimitry Andric                  .addUse(getSPIRVTypeID(BaseType));
14185f757f3fSDimitry Andric   DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
14195f757f3fSDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
142081ad6265SDimitry Andric }
142181ad6265SDimitry Andric 
142281ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
1423*0fca6ea1SDimitry Andric     SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &,
1424bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC) {
1425*0fca6ea1SDimitry Andric   MachineIRBuilder MIRBuilder(I);
1426*0fca6ea1SDimitry Andric   return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);
1427fcaf7f86SDimitry Andric }
1428fcaf7f86SDimitry Andric 
1429fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
1430fcaf7f86SDimitry Andric                                                SPIRVType *SpvType,
1431fcaf7f86SDimitry Andric                                                const SPIRVInstrInfo &TII) {
1432fcaf7f86SDimitry Andric   assert(SpvType);
1433fcaf7f86SDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1434fcaf7f86SDimitry Andric   assert(LLVMTy);
1435fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
1436fcaf7f86SDimitry Andric   UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1437fcaf7f86SDimitry Andric   Register Res = DT.find(UV, CurMF);
1438fcaf7f86SDimitry Andric   if (Res.isValid())
1439fcaf7f86SDimitry Andric     return Res;
1440fcaf7f86SDimitry Andric   LLT LLTy = LLT::scalar(32);
1441fcaf7f86SDimitry Andric   Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
144206c3fb27SDimitry Andric   CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1443fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1444fcaf7f86SDimitry Andric   DT.add(UV, CurMF, Res);
1445fcaf7f86SDimitry Andric 
1446fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
1447fcaf7f86SDimitry Andric   MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1448fcaf7f86SDimitry Andric             .addDef(Res)
1449fcaf7f86SDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
1450fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
1451fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1452fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
1453fcaf7f86SDimitry Andric   return Res;
145481ad6265SDimitry Andric }
1455