xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
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"
2381ad6265SDimitry Andric 
2481ad6265SDimitry Andric using namespace llvm;
2581ad6265SDimitry Andric SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize)
2681ad6265SDimitry Andric     : PointerSize(PointerSize) {}
2781ad6265SDimitry Andric 
28fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignIntTypeToVReg(unsigned BitWidth,
29fcaf7f86SDimitry Andric                                                     Register VReg,
30fcaf7f86SDimitry Andric                                                     MachineInstr &I,
31fcaf7f86SDimitry Andric                                                     const SPIRVInstrInfo &TII) {
32fcaf7f86SDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
33fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
34fcaf7f86SDimitry Andric   return SpirvType;
35fcaf7f86SDimitry Andric }
36fcaf7f86SDimitry Andric 
37fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignVectTypeToVReg(
38fcaf7f86SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,
39fcaf7f86SDimitry Andric     const SPIRVInstrInfo &TII) {
40fcaf7f86SDimitry Andric   SPIRVType *SpirvType =
41fcaf7f86SDimitry Andric       getOrCreateSPIRVVectorType(BaseType, NumElements, I, TII);
42fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);
43fcaf7f86SDimitry Andric   return SpirvType;
44fcaf7f86SDimitry Andric }
45fcaf7f86SDimitry Andric 
4681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::assignTypeToVReg(
4781ad6265SDimitry Andric     const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,
48bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
4981ad6265SDimitry Andric 
5081ad6265SDimitry Andric   SPIRVType *SpirvType =
5181ad6265SDimitry Andric       getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);
5281ad6265SDimitry Andric   assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());
5381ad6265SDimitry Andric   return SpirvType;
5481ad6265SDimitry Andric }
5581ad6265SDimitry Andric 
5681ad6265SDimitry Andric void SPIRVGlobalRegistry::assignSPIRVTypeToVReg(SPIRVType *SpirvType,
5781ad6265SDimitry Andric                                                 Register VReg,
5881ad6265SDimitry Andric                                                 MachineFunction &MF) {
5981ad6265SDimitry Andric   VRegToTypeMap[&MF][VReg] = SpirvType;
6081ad6265SDimitry Andric }
6181ad6265SDimitry Andric 
6281ad6265SDimitry Andric static Register createTypeVReg(MachineIRBuilder &MIRBuilder) {
6381ad6265SDimitry Andric   auto &MRI = MIRBuilder.getMF().getRegInfo();
6481ad6265SDimitry Andric   auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
6581ad6265SDimitry Andric   MRI.setRegClass(Res, &SPIRV::TYPERegClass);
6681ad6265SDimitry Andric   return Res;
6781ad6265SDimitry Andric }
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric static Register createTypeVReg(MachineRegisterInfo &MRI) {
7081ad6265SDimitry Andric   auto Res = MRI.createGenericVirtualRegister(LLT::scalar(32));
7181ad6265SDimitry Andric   MRI.setRegClass(Res, &SPIRV::TYPERegClass);
7281ad6265SDimitry Andric   return Res;
7381ad6265SDimitry Andric }
7481ad6265SDimitry Andric 
7581ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
7681ad6265SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
7781ad6265SDimitry Andric       .addDef(createTypeVReg(MIRBuilder));
7881ad6265SDimitry Andric }
7981ad6265SDimitry Andric 
8081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width,
8181ad6265SDimitry Andric                                              MachineIRBuilder &MIRBuilder,
8281ad6265SDimitry Andric                                              bool IsSigned) {
8306c3fb27SDimitry Andric   assert(Width <= 64 && "Unsupported integer width!");
845f757f3fSDimitry Andric   const SPIRVSubtarget &ST =
855f757f3fSDimitry Andric       cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
865f757f3fSDimitry Andric   if (ST.canUseExtension(
875f757f3fSDimitry Andric           SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) {
885f757f3fSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpExtension)
895f757f3fSDimitry Andric         .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers);
905f757f3fSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpCapability)
915f757f3fSDimitry Andric         .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL);
925f757f3fSDimitry Andric   } else if (Width <= 8)
9306c3fb27SDimitry Andric     Width = 8;
9406c3fb27SDimitry Andric   else if (Width <= 16)
9506c3fb27SDimitry Andric     Width = 16;
9606c3fb27SDimitry Andric   else if (Width <= 32)
9706c3fb27SDimitry Andric     Width = 32;
9806c3fb27SDimitry Andric   else if (Width <= 64)
9906c3fb27SDimitry Andric     Width = 64;
10006c3fb27SDimitry Andric 
10181ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
10281ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
10381ad6265SDimitry Andric                  .addImm(Width)
10481ad6265SDimitry Andric                  .addImm(IsSigned ? 1 : 0);
10581ad6265SDimitry Andric   return MIB;
10681ad6265SDimitry Andric }
10781ad6265SDimitry Andric 
10881ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
10981ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder) {
11081ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
11181ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
11281ad6265SDimitry Andric                  .addImm(Width);
11381ad6265SDimitry Andric   return MIB;
11481ad6265SDimitry Andric }
11581ad6265SDimitry Andric 
11681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
11781ad6265SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
11881ad6265SDimitry Andric       .addDef(createTypeVReg(MIRBuilder));
11981ad6265SDimitry Andric }
12081ad6265SDimitry Andric 
12181ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
12281ad6265SDimitry Andric                                                 SPIRVType *ElemType,
12381ad6265SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
12481ad6265SDimitry Andric   auto EleOpc = ElemType->getOpcode();
12581ad6265SDimitry Andric   assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
12681ad6265SDimitry Andric           EleOpc == SPIRV::OpTypeBool) &&
12781ad6265SDimitry Andric          "Invalid vector element type");
12881ad6265SDimitry Andric 
12981ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
13081ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
13181ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
13281ad6265SDimitry Andric                  .addImm(NumElems);
13381ad6265SDimitry Andric   return MIB;
13481ad6265SDimitry Andric }
13581ad6265SDimitry Andric 
136fcaf7f86SDimitry Andric std::tuple<Register, ConstantInt *, bool>
137fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
138fcaf7f86SDimitry Andric                                             MachineIRBuilder *MIRBuilder,
139fcaf7f86SDimitry Andric                                             MachineInstr *I,
140fcaf7f86SDimitry Andric                                             const SPIRVInstrInfo *TII) {
141fcaf7f86SDimitry Andric   const IntegerType *LLVMIntTy;
142fcaf7f86SDimitry Andric   if (SpvType)
143fcaf7f86SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
144fcaf7f86SDimitry Andric   else
145fcaf7f86SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(CurMF->getFunction().getContext());
146fcaf7f86SDimitry Andric   bool NewInstr = false;
147fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
148fcaf7f86SDimitry Andric   ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
149fcaf7f86SDimitry Andric   Register Res = DT.find(CI, CurMF);
150fcaf7f86SDimitry Andric   if (!Res.isValid()) {
151fcaf7f86SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
152fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
153fcaf7f86SDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
15406c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
155fcaf7f86SDimitry Andric     if (MIRBuilder)
156fcaf7f86SDimitry Andric       assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
157fcaf7f86SDimitry Andric     else
158fcaf7f86SDimitry Andric       assignIntTypeToVReg(BitWidth, Res, *I, *TII);
159fcaf7f86SDimitry Andric     DT.add(CI, CurMF, Res);
160fcaf7f86SDimitry Andric     NewInstr = true;
161fcaf7f86SDimitry Andric   }
162fcaf7f86SDimitry Andric   return std::make_tuple(Res, CI, NewInstr);
163fcaf7f86SDimitry Andric }
164fcaf7f86SDimitry Andric 
165fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
166fcaf7f86SDimitry Andric                                                   SPIRVType *SpvType,
167fcaf7f86SDimitry Andric                                                   const SPIRVInstrInfo &TII) {
168fcaf7f86SDimitry Andric   assert(SpvType);
169fcaf7f86SDimitry Andric   ConstantInt *CI;
170fcaf7f86SDimitry Andric   Register Res;
171fcaf7f86SDimitry Andric   bool New;
172fcaf7f86SDimitry Andric   std::tie(Res, CI, New) =
173fcaf7f86SDimitry Andric       getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
174fcaf7f86SDimitry Andric   // If we have found Res register which is defined by the passed G_CONSTANT
175fcaf7f86SDimitry Andric   // machine instruction, a new constant instruction should be created.
176fcaf7f86SDimitry Andric   if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
177fcaf7f86SDimitry Andric     return Res;
178fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
179fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
180fcaf7f86SDimitry Andric   if (Val) {
181fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
182fcaf7f86SDimitry Andric               .addDef(Res)
183fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
184fcaf7f86SDimitry Andric     addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
185fcaf7f86SDimitry Andric   } else {
186fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
187fcaf7f86SDimitry Andric               .addDef(Res)
188fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
189fcaf7f86SDimitry Andric   }
190fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
191fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
192fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
193fcaf7f86SDimitry Andric   return Res;
194fcaf7f86SDimitry Andric }
195fcaf7f86SDimitry Andric 
19681ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
19781ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
19881ad6265SDimitry Andric                                                SPIRVType *SpvType,
19981ad6265SDimitry Andric                                                bool EmitIR) {
20081ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
20181ad6265SDimitry Andric   const IntegerType *LLVMIntTy;
20281ad6265SDimitry Andric   if (SpvType)
20381ad6265SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
20481ad6265SDimitry Andric   else
20581ad6265SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
20681ad6265SDimitry Andric   // Find a constant in DT or build a new one.
20781ad6265SDimitry Andric   const auto ConstInt =
20881ad6265SDimitry Andric       ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
209753f127fSDimitry Andric   Register Res = DT.find(ConstInt, &MF);
210753f127fSDimitry Andric   if (!Res.isValid()) {
21181ad6265SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
212fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
213fcaf7f86SDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
21406c3fb27SDimitry Andric     MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
215fcaf7f86SDimitry Andric     assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
216fcaf7f86SDimitry Andric                      SPIRV::AccessQualifier::ReadWrite, EmitIR);
217fcaf7f86SDimitry Andric     DT.add(ConstInt, &MIRBuilder.getMF(), Res);
218fcaf7f86SDimitry Andric     if (EmitIR) {
21981ad6265SDimitry Andric       MIRBuilder.buildConstant(Res, *ConstInt);
220fcaf7f86SDimitry Andric     } else {
221fcaf7f86SDimitry Andric       MachineInstrBuilder MIB;
222fcaf7f86SDimitry Andric       if (Val) {
223fcaf7f86SDimitry Andric         assert(SpvType);
224fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
22581ad6265SDimitry Andric                   .addDef(Res)
226fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
227fcaf7f86SDimitry Andric         addNumImm(APInt(BitWidth, Val), MIB);
228fcaf7f86SDimitry Andric       } else {
229fcaf7f86SDimitry Andric         assert(SpvType);
230fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
231fcaf7f86SDimitry Andric                   .addDef(Res)
232fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
233fcaf7f86SDimitry Andric       }
234fcaf7f86SDimitry Andric       const auto &Subtarget = CurMF->getSubtarget();
235fcaf7f86SDimitry Andric       constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
236fcaf7f86SDimitry Andric                                        *Subtarget.getRegisterInfo(),
237fcaf7f86SDimitry Andric                                        *Subtarget.getRegBankInfo());
238fcaf7f86SDimitry Andric     }
239753f127fSDimitry Andric   }
24081ad6265SDimitry Andric   return Res;
24181ad6265SDimitry Andric }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,
24481ad6265SDimitry Andric                                               MachineIRBuilder &MIRBuilder,
24581ad6265SDimitry Andric                                               SPIRVType *SpvType) {
24681ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
2475f757f3fSDimitry Andric   auto &Ctx = MF.getFunction().getContext();
2485f757f3fSDimitry Andric   if (!SpvType) {
2495f757f3fSDimitry Andric     const Type *LLVMFPTy = Type::getFloatTy(Ctx);
2505f757f3fSDimitry Andric     SpvType = getOrCreateSPIRVType(LLVMFPTy, MIRBuilder);
25181ad6265SDimitry Andric   }
25281ad6265SDimitry Andric   // Find a constant in DT or build a new one.
2535f757f3fSDimitry Andric   const auto ConstFP = ConstantFP::get(Ctx, Val);
254753f127fSDimitry Andric   Register Res = DT.find(ConstFP, &MF);
255753f127fSDimitry Andric   if (!Res.isValid()) {
2565f757f3fSDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(32));
25706c3fb27SDimitry Andric     MF.getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
2585f757f3fSDimitry Andric     assignSPIRVTypeToVReg(SpvType, Res, MF);
259fcaf7f86SDimitry Andric     DT.add(ConstFP, &MF, Res);
2605f757f3fSDimitry Andric 
2615f757f3fSDimitry Andric     MachineInstrBuilder MIB;
2625f757f3fSDimitry Andric     MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)
2635f757f3fSDimitry Andric               .addDef(Res)
2645f757f3fSDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
2655f757f3fSDimitry Andric     addNumImm(ConstFP->getValueAPF().bitcastToAPInt(), MIB);
266753f127fSDimitry Andric   }
2675f757f3fSDimitry Andric 
26881ad6265SDimitry Andric   return Res;
26981ad6265SDimitry Andric }
27081ad6265SDimitry Andric 
271bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
272bdd1243dSDimitry Andric     uint64_t Val, MachineInstr &I, SPIRVType *SpvType,
273bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
274bdd1243dSDimitry Andric     unsigned ElemCnt) {
275fcaf7f86SDimitry Andric   // Find a constant vector in DT or build a new one.
276bdd1243dSDimitry Andric   Register Res = DT.find(CA, CurMF);
277fcaf7f86SDimitry Andric   if (!Res.isValid()) {
278fcaf7f86SDimitry Andric     SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
279fcaf7f86SDimitry Andric     // SpvScalConst should be created before SpvVecConst to avoid undefined ID
280fcaf7f86SDimitry Andric     // error on validation.
281fcaf7f86SDimitry Andric     // TODO: can moved below once sorting of types/consts/defs is implemented.
282fcaf7f86SDimitry Andric     Register SpvScalConst;
283fcaf7f86SDimitry Andric     if (Val)
284fcaf7f86SDimitry Andric       SpvScalConst = getOrCreateConstInt(Val, I, SpvBaseType, TII);
285fcaf7f86SDimitry Andric     // TODO: maybe use bitwidth of base type.
286fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
287fcaf7f86SDimitry Andric     Register SpvVecConst =
288fcaf7f86SDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
28906c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
290bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
291bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
292fcaf7f86SDimitry Andric     MachineInstrBuilder MIB;
293fcaf7f86SDimitry Andric     MachineBasicBlock &BB = *I.getParent();
294fcaf7f86SDimitry Andric     if (Val) {
295fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
296fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
297fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
298fcaf7f86SDimitry Andric       for (unsigned i = 0; i < ElemCnt; ++i)
299fcaf7f86SDimitry Andric         MIB.addUse(SpvScalConst);
300fcaf7f86SDimitry Andric     } else {
301fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
302fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
303fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
304fcaf7f86SDimitry Andric     }
305fcaf7f86SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
306fcaf7f86SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
307fcaf7f86SDimitry Andric                                      *Subtarget.getRegisterInfo(),
308fcaf7f86SDimitry Andric                                      *Subtarget.getRegBankInfo());
309fcaf7f86SDimitry Andric     return SpvVecConst;
310fcaf7f86SDimitry Andric   }
311fcaf7f86SDimitry Andric   return Res;
312fcaf7f86SDimitry Andric }
313fcaf7f86SDimitry Andric 
314bdd1243dSDimitry Andric Register
315bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val, MachineInstr &I,
316bdd1243dSDimitry Andric                                               SPIRVType *SpvType,
317bdd1243dSDimitry Andric                                               const SPIRVInstrInfo &TII) {
318bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
319bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
320bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
321bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
322bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
323bdd1243dSDimitry Andric   auto ConstVec =
324bdd1243dSDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
325bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
326bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstVec, BW,
327bdd1243dSDimitry Andric                                        SpvType->getOperand(2).getImm());
328bdd1243dSDimitry Andric }
329bdd1243dSDimitry Andric 
330bdd1243dSDimitry Andric Register
331bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntArray(uint64_t Val, MachineInstr &I,
332bdd1243dSDimitry Andric                                              SPIRVType *SpvType,
333bdd1243dSDimitry Andric                                              const SPIRVInstrInfo &TII) {
334bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
335bdd1243dSDimitry Andric   assert(LLVMTy->isArrayTy());
336bdd1243dSDimitry Andric   const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
337bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMArrTy->getElementType();
338bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
339bdd1243dSDimitry Andric   auto ConstArr =
340bdd1243dSDimitry Andric       ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
341bdd1243dSDimitry Andric   SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
342bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
343bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstArr, BW,
344bdd1243dSDimitry Andric                                        LLVMArrTy->getNumElements());
345bdd1243dSDimitry Andric }
346bdd1243dSDimitry Andric 
347bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
348bdd1243dSDimitry Andric     uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
349bdd1243dSDimitry Andric     Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
350bdd1243dSDimitry Andric   Register Res = DT.find(CA, CurMF);
351bdd1243dSDimitry Andric   if (!Res.isValid()) {
352bdd1243dSDimitry Andric     Register SpvScalConst;
353bdd1243dSDimitry Andric     if (Val || EmitIR) {
354bdd1243dSDimitry Andric       SPIRVType *SpvBaseType =
355bdd1243dSDimitry Andric           getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
356bdd1243dSDimitry Andric       SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
357bdd1243dSDimitry Andric     }
358bdd1243dSDimitry Andric     LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
359bdd1243dSDimitry Andric     Register SpvVecConst =
360bdd1243dSDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
36106c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(SpvVecConst, &SPIRV::IDRegClass);
362bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
363bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
364bdd1243dSDimitry Andric     if (EmitIR) {
365bdd1243dSDimitry Andric       MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
366bdd1243dSDimitry Andric     } else {
367bdd1243dSDimitry Andric       if (Val) {
368bdd1243dSDimitry Andric         auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
369bdd1243dSDimitry Andric                        .addDef(SpvVecConst)
370bdd1243dSDimitry Andric                        .addUse(getSPIRVTypeID(SpvType));
371bdd1243dSDimitry Andric         for (unsigned i = 0; i < ElemCnt; ++i)
372bdd1243dSDimitry Andric           MIB.addUse(SpvScalConst);
373bdd1243dSDimitry Andric       } else {
374bdd1243dSDimitry Andric         MIRBuilder.buildInstr(SPIRV::OpConstantNull)
375bdd1243dSDimitry Andric             .addDef(SpvVecConst)
376bdd1243dSDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
377bdd1243dSDimitry Andric       }
378bdd1243dSDimitry Andric     }
379bdd1243dSDimitry Andric     return SpvVecConst;
380bdd1243dSDimitry Andric   }
381bdd1243dSDimitry Andric   return Res;
382bdd1243dSDimitry Andric }
383bdd1243dSDimitry Andric 
384bdd1243dSDimitry Andric Register
385bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val,
386bdd1243dSDimitry Andric                                               MachineIRBuilder &MIRBuilder,
387bdd1243dSDimitry Andric                                               SPIRVType *SpvType, bool EmitIR) {
388bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
389bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
390bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
391bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
392bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
393bdd1243dSDimitry Andric   auto ConstVec =
394bdd1243dSDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
395bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
396bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
397bdd1243dSDimitry Andric                                        ConstVec, BW,
398bdd1243dSDimitry Andric                                        SpvType->getOperand(2).getImm());
399bdd1243dSDimitry Andric }
400bdd1243dSDimitry Andric 
401bdd1243dSDimitry Andric Register
402bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntArray(uint64_t Val,
403bdd1243dSDimitry Andric                                              MachineIRBuilder &MIRBuilder,
404bdd1243dSDimitry Andric                                              SPIRVType *SpvType, bool EmitIR) {
405bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
406bdd1243dSDimitry Andric   assert(LLVMTy->isArrayTy());
407bdd1243dSDimitry Andric   const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
408bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMArrTy->getElementType();
409bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
410bdd1243dSDimitry Andric   auto ConstArr =
411bdd1243dSDimitry Andric       ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
412bdd1243dSDimitry Andric   SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
413bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
414bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
415bdd1243dSDimitry Andric                                        ConstArr, BW,
416bdd1243dSDimitry Andric                                        LLVMArrTy->getNumElements());
417bdd1243dSDimitry Andric }
418bdd1243dSDimitry Andric 
419bdd1243dSDimitry Andric Register
420bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
421bdd1243dSDimitry Andric                                              SPIRVType *SpvType) {
422bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
423bdd1243dSDimitry Andric   const PointerType *LLVMPtrTy = cast<PointerType>(LLVMTy);
424bdd1243dSDimitry Andric   // Find a constant in DT or build a new one.
425bdd1243dSDimitry Andric   Constant *CP = ConstantPointerNull::get(const_cast<PointerType *>(LLVMPtrTy));
426bdd1243dSDimitry Andric   Register Res = DT.find(CP, CurMF);
427bdd1243dSDimitry Andric   if (!Res.isValid()) {
428bdd1243dSDimitry Andric     LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
429bdd1243dSDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
43006c3fb27SDimitry Andric     CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
431bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
432bdd1243dSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpConstantNull)
433bdd1243dSDimitry Andric         .addDef(Res)
434bdd1243dSDimitry Andric         .addUse(getSPIRVTypeID(SpvType));
435bdd1243dSDimitry Andric     DT.add(CP, CurMF, Res);
436bdd1243dSDimitry Andric   }
437bdd1243dSDimitry Andric   return Res;
438bdd1243dSDimitry Andric }
439bdd1243dSDimitry Andric 
440bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::buildConstantSampler(
441bdd1243dSDimitry Andric     Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
442bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
443bdd1243dSDimitry Andric   SPIRVType *SampTy;
444bdd1243dSDimitry Andric   if (SpvType)
445bdd1243dSDimitry Andric     SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
446bdd1243dSDimitry Andric   else
447bdd1243dSDimitry Andric     SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t", MIRBuilder);
448bdd1243dSDimitry Andric 
449bdd1243dSDimitry Andric   auto Sampler =
450bdd1243dSDimitry Andric       ResReg.isValid()
451bdd1243dSDimitry Andric           ? ResReg
452bdd1243dSDimitry Andric           : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
453bdd1243dSDimitry Andric   auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
454bdd1243dSDimitry Andric                  .addDef(Sampler)
455bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(SampTy))
456bdd1243dSDimitry Andric                  .addImm(AddrMode)
457bdd1243dSDimitry Andric                  .addImm(Param)
458bdd1243dSDimitry Andric                  .addImm(FilerMode);
459bdd1243dSDimitry Andric   assert(Res->getOperand(0).isReg());
460bdd1243dSDimitry Andric   return Res->getOperand(0).getReg();
461bdd1243dSDimitry Andric }
462bdd1243dSDimitry Andric 
46381ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildGlobalVariable(
46481ad6265SDimitry Andric     Register ResVReg, SPIRVType *BaseType, StringRef Name,
465bdd1243dSDimitry Andric     const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
46681ad6265SDimitry Andric     const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
467bdd1243dSDimitry Andric     SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
46881ad6265SDimitry Andric     bool IsInstSelector) {
46981ad6265SDimitry Andric   const GlobalVariable *GVar = nullptr;
47081ad6265SDimitry Andric   if (GV)
47181ad6265SDimitry Andric     GVar = cast<const GlobalVariable>(GV);
47281ad6265SDimitry Andric   else {
47381ad6265SDimitry Andric     // If GV is not passed explicitly, use the name to find or construct
47481ad6265SDimitry Andric     // the global variable.
47581ad6265SDimitry Andric     Module *M = MIRBuilder.getMF().getFunction().getParent();
47681ad6265SDimitry Andric     GVar = M->getGlobalVariable(Name);
47781ad6265SDimitry Andric     if (GVar == nullptr) {
47881ad6265SDimitry Andric       const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
47981ad6265SDimitry Andric       GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
48081ad6265SDimitry Andric                                 GlobalValue::ExternalLinkage, nullptr,
48181ad6265SDimitry Andric                                 Twine(Name));
48281ad6265SDimitry Andric     }
48381ad6265SDimitry Andric     GV = GVar;
48481ad6265SDimitry Andric   }
485fcaf7f86SDimitry Andric   Register Reg = DT.find(GVar, &MIRBuilder.getMF());
486fcaf7f86SDimitry Andric   if (Reg.isValid()) {
487fcaf7f86SDimitry Andric     if (Reg != ResVReg)
488fcaf7f86SDimitry Andric       MIRBuilder.buildCopy(ResVReg, Reg);
489fcaf7f86SDimitry Andric     return ResVReg;
490fcaf7f86SDimitry Andric   }
491fcaf7f86SDimitry Andric 
49281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
49381ad6265SDimitry Andric                  .addDef(ResVReg)
49481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
49581ad6265SDimitry Andric                  .addImm(static_cast<uint32_t>(Storage));
49681ad6265SDimitry Andric 
49781ad6265SDimitry Andric   if (Init != 0) {
49881ad6265SDimitry Andric     MIB.addUse(Init->getOperand(0).getReg());
49981ad6265SDimitry Andric   }
50081ad6265SDimitry Andric 
50181ad6265SDimitry Andric   // ISel may introduce a new register on this step, so we need to add it to
50281ad6265SDimitry Andric   // DT and correct its type avoiding fails on the next stage.
50381ad6265SDimitry Andric   if (IsInstSelector) {
50481ad6265SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
50581ad6265SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
50681ad6265SDimitry Andric                                      *Subtarget.getRegisterInfo(),
50781ad6265SDimitry Andric                                      *Subtarget.getRegBankInfo());
50881ad6265SDimitry Andric   }
50981ad6265SDimitry Andric   Reg = MIB->getOperand(0).getReg();
510753f127fSDimitry Andric   DT.add(GVar, &MIRBuilder.getMF(), Reg);
51181ad6265SDimitry Andric 
51281ad6265SDimitry Andric   // Set to Reg the same type as ResVReg has.
51381ad6265SDimitry Andric   auto MRI = MIRBuilder.getMRI();
51481ad6265SDimitry Andric   assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
51581ad6265SDimitry Andric   if (Reg != ResVReg) {
51681ad6265SDimitry Andric     LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
51781ad6265SDimitry Andric     MRI->setType(Reg, RegLLTy);
51881ad6265SDimitry Andric     assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
51981ad6265SDimitry Andric   }
52081ad6265SDimitry Andric 
52181ad6265SDimitry Andric   // If it's a global variable with name, output OpName for it.
52281ad6265SDimitry Andric   if (GVar && GVar->hasName())
52381ad6265SDimitry Andric     buildOpName(Reg, GVar->getName(), MIRBuilder);
52481ad6265SDimitry Andric 
52581ad6265SDimitry Andric   // Output decorations for the GV.
52681ad6265SDimitry Andric   // TODO: maybe move to GenerateDecorations pass.
52781ad6265SDimitry Andric   if (IsConst)
52881ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
52981ad6265SDimitry Andric 
530bdd1243dSDimitry Andric   if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
531bdd1243dSDimitry Andric     unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
532bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
533bdd1243dSDimitry Andric   }
53481ad6265SDimitry Andric 
53581ad6265SDimitry Andric   if (HasLinkageTy)
53681ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
53781ad6265SDimitry Andric                     {static_cast<uint32_t>(LinkageType)}, Name);
538bdd1243dSDimitry Andric 
539bdd1243dSDimitry Andric   SPIRV::BuiltIn::BuiltIn BuiltInId;
540bdd1243dSDimitry Andric   if (getSpirvBuiltInIdByName(Name, BuiltInId))
541bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
542bdd1243dSDimitry Andric                     {static_cast<uint32_t>(BuiltInId)});
543bdd1243dSDimitry Andric 
54481ad6265SDimitry Andric   return Reg;
54581ad6265SDimitry Andric }
54681ad6265SDimitry Andric 
54781ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
54881ad6265SDimitry Andric                                                SPIRVType *ElemType,
54981ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
55081ad6265SDimitry Andric                                                bool EmitIR) {
55181ad6265SDimitry Andric   assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
55281ad6265SDimitry Andric          "Invalid array element type");
55381ad6265SDimitry Andric   Register NumElementsVReg =
55481ad6265SDimitry Andric       buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
55581ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
55681ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
55781ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
55881ad6265SDimitry Andric                  .addUse(NumElementsVReg);
55981ad6265SDimitry Andric   return MIB;
56081ad6265SDimitry Andric }
56181ad6265SDimitry Andric 
562fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
563fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
564fcaf7f86SDimitry Andric   assert(Ty->hasName());
565fcaf7f86SDimitry Andric   const StringRef Name = Ty->hasName() ? Ty->getName() : "";
566fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
567fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
568fcaf7f86SDimitry Andric   addStringImm(Name, MIB);
569fcaf7f86SDimitry Andric   buildOpName(ResVReg, Name, MIRBuilder);
570fcaf7f86SDimitry Andric   return MIB;
571fcaf7f86SDimitry Andric }
572fcaf7f86SDimitry Andric 
573fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
574fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder,
575fcaf7f86SDimitry Andric                                                 bool EmitIR) {
576fcaf7f86SDimitry Andric   SmallVector<Register, 4> FieldTypes;
577fcaf7f86SDimitry Andric   for (const auto &Elem : Ty->elements()) {
578fcaf7f86SDimitry Andric     SPIRVType *ElemTy = findSPIRVType(Elem, MIRBuilder);
579fcaf7f86SDimitry Andric     assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
580fcaf7f86SDimitry Andric            "Invalid struct element type");
581fcaf7f86SDimitry Andric     FieldTypes.push_back(getSPIRVTypeID(ElemTy));
582fcaf7f86SDimitry Andric   }
583fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
584fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
585fcaf7f86SDimitry Andric   for (const auto &Ty : FieldTypes)
586fcaf7f86SDimitry Andric     MIB.addUse(Ty);
587fcaf7f86SDimitry Andric   if (Ty->hasName())
588fcaf7f86SDimitry Andric     buildOpName(ResVReg, Ty->getName(), MIRBuilder);
589fcaf7f86SDimitry Andric   if (Ty->isPacked())
590fcaf7f86SDimitry Andric     buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
591fcaf7f86SDimitry Andric   return MIB;
592fcaf7f86SDimitry Andric }
593fcaf7f86SDimitry Andric 
594bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
595bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
596bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual) {
59706c3fb27SDimitry Andric   assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");
59806c3fb27SDimitry Andric   return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);
599fcaf7f86SDimitry Andric }
600fcaf7f86SDimitry Andric 
601bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
602bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
603bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, Register Reg) {
604fcaf7f86SDimitry Andric   if (!Reg.isValid())
605fcaf7f86SDimitry Andric     Reg = createTypeVReg(MIRBuilder);
606fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
607fcaf7f86SDimitry Andric       .addDef(Reg)
60881ad6265SDimitry Andric       .addImm(static_cast<uint32_t>(SC))
60981ad6265SDimitry Andric       .addUse(getSPIRVTypeID(ElemType));
610fcaf7f86SDimitry Andric }
611fcaf7f86SDimitry Andric 
612bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
613bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
614fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
615fcaf7f86SDimitry Andric       .addUse(createTypeVReg(MIRBuilder))
616fcaf7f86SDimitry Andric       .addImm(static_cast<uint32_t>(SC));
61781ad6265SDimitry Andric }
61881ad6265SDimitry Andric 
61981ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
62081ad6265SDimitry Andric     SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
62181ad6265SDimitry Andric     MachineIRBuilder &MIRBuilder) {
62281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
62381ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
62481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(RetType));
62581ad6265SDimitry Andric   for (const SPIRVType *ArgType : ArgTypes)
62681ad6265SDimitry Andric     MIB.addUse(getSPIRVTypeID(ArgType));
62781ad6265SDimitry Andric   return MIB;
62881ad6265SDimitry Andric }
62981ad6265SDimitry Andric 
630fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(
631fcaf7f86SDimitry Andric     const Type *Ty, SPIRVType *RetType,
632fcaf7f86SDimitry Andric     const SmallVectorImpl<SPIRVType *> &ArgTypes,
633fcaf7f86SDimitry Andric     MachineIRBuilder &MIRBuilder) {
634fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
635fcaf7f86SDimitry Andric   if (Reg.isValid())
636fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
637fcaf7f86SDimitry Andric   SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
6385f757f3fSDimitry Andric   DT.add(Ty, CurMF, getSPIRVTypeID(SpirvType));
639fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(Ty, SpirvType);
640fcaf7f86SDimitry Andric }
641fcaf7f86SDimitry Andric 
642bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
643bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
644bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
645fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
646fcaf7f86SDimitry Andric   if (Reg.isValid())
647fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
648*cb14a3feSDimitry Andric   if (ForwardPointerTypes.contains(Ty))
649fcaf7f86SDimitry Andric     return ForwardPointerTypes[Ty];
650fcaf7f86SDimitry Andric   return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
651fcaf7f86SDimitry Andric }
652fcaf7f86SDimitry Andric 
653fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getSPIRVTypeID(const SPIRVType *SpirvType) const {
654fcaf7f86SDimitry Andric   assert(SpirvType && "Attempting to get type id for nullptr type.");
655fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
656fcaf7f86SDimitry Andric     return SpirvType->uses().begin()->getReg();
657fcaf7f86SDimitry Andric   return SpirvType->defs().begin()->getReg();
658fcaf7f86SDimitry Andric }
659fcaf7f86SDimitry Andric 
660bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
661bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
662bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
663bdd1243dSDimitry Andric   if (isSpecialOpaqueType(Ty))
664bdd1243dSDimitry Andric     return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
665fcaf7f86SDimitry Andric   auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
666fcaf7f86SDimitry Andric   auto t = TypeToSPIRVTypeMap.find(Ty);
667fcaf7f86SDimitry Andric   if (t != TypeToSPIRVTypeMap.end()) {
668fcaf7f86SDimitry Andric     auto tt = t->second.find(&MIRBuilder.getMF());
669fcaf7f86SDimitry Andric     if (tt != t->second.end())
670fcaf7f86SDimitry Andric       return getSPIRVTypeForVReg(tt->second);
671fcaf7f86SDimitry Andric   }
672fcaf7f86SDimitry Andric 
67381ad6265SDimitry Andric   if (auto IType = dyn_cast<IntegerType>(Ty)) {
67481ad6265SDimitry Andric     const unsigned Width = IType->getBitWidth();
67581ad6265SDimitry Andric     return Width == 1 ? getOpTypeBool(MIRBuilder)
67681ad6265SDimitry Andric                       : getOpTypeInt(Width, MIRBuilder, false);
67781ad6265SDimitry Andric   }
67881ad6265SDimitry Andric   if (Ty->isFloatingPointTy())
67981ad6265SDimitry Andric     return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
68081ad6265SDimitry Andric   if (Ty->isVoidTy())
68181ad6265SDimitry Andric     return getOpTypeVoid(MIRBuilder);
68281ad6265SDimitry Andric   if (Ty->isVectorTy()) {
683fcaf7f86SDimitry Andric     SPIRVType *El =
684fcaf7f86SDimitry Andric         findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
68581ad6265SDimitry Andric     return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
68681ad6265SDimitry Andric                            MIRBuilder);
68781ad6265SDimitry Andric   }
68881ad6265SDimitry Andric   if (Ty->isArrayTy()) {
689fcaf7f86SDimitry Andric     SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
69081ad6265SDimitry Andric     return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
69181ad6265SDimitry Andric   }
692fcaf7f86SDimitry Andric   if (auto SType = dyn_cast<StructType>(Ty)) {
693fcaf7f86SDimitry Andric     if (SType->isOpaque())
694fcaf7f86SDimitry Andric       return getOpTypeOpaque(SType, MIRBuilder);
695fcaf7f86SDimitry Andric     return getOpTypeStruct(SType, MIRBuilder, EmitIR);
696fcaf7f86SDimitry Andric   }
69781ad6265SDimitry Andric   if (auto FType = dyn_cast<FunctionType>(Ty)) {
698fcaf7f86SDimitry Andric     SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
69981ad6265SDimitry Andric     SmallVector<SPIRVType *, 4> ParamTypes;
70081ad6265SDimitry Andric     for (const auto &t : FType->params()) {
701fcaf7f86SDimitry Andric       ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
70281ad6265SDimitry Andric     }
70381ad6265SDimitry Andric     return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
70481ad6265SDimitry Andric   }
70581ad6265SDimitry Andric   if (auto PType = dyn_cast<PointerType>(Ty)) {
70681ad6265SDimitry Andric     SPIRVType *SpvElementType;
70781ad6265SDimitry Andric     // At the moment, all opaque pointers correspond to i8 element type.
70881ad6265SDimitry Andric     // TODO: change the implementation once opaque pointers are supported
70981ad6265SDimitry Andric     // in the SPIR-V specification.
71081ad6265SDimitry Andric     SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
71181ad6265SDimitry Andric     auto SC = addressSpaceToStorageClass(PType->getAddressSpace());
712fcaf7f86SDimitry Andric     // Null pointer means we have a loop in type definitions, make and
713fcaf7f86SDimitry Andric     // return corresponding OpTypeForwardPointer.
714fcaf7f86SDimitry Andric     if (SpvElementType == nullptr) {
715*cb14a3feSDimitry Andric       if (!ForwardPointerTypes.contains(Ty))
716fcaf7f86SDimitry Andric         ForwardPointerTypes[PType] = getOpTypeForwardPointer(SC, MIRBuilder);
717fcaf7f86SDimitry Andric       return ForwardPointerTypes[PType];
718fcaf7f86SDimitry Andric     }
719fcaf7f86SDimitry Andric     Register Reg(0);
720fcaf7f86SDimitry Andric     // If we have forward pointer associated with this type, use its register
721fcaf7f86SDimitry Andric     // operand to create OpTypePointer.
722*cb14a3feSDimitry Andric     if (ForwardPointerTypes.contains(PType))
723fcaf7f86SDimitry Andric       Reg = getSPIRVTypeID(ForwardPointerTypes[PType]);
724fcaf7f86SDimitry Andric 
725fcaf7f86SDimitry Andric     return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
72681ad6265SDimitry Andric   }
72781ad6265SDimitry Andric   llvm_unreachable("Unable to convert LLVM type to SPIRVType");
72881ad6265SDimitry Andric }
72981ad6265SDimitry Andric 
730fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
731fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
732bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
733fcaf7f86SDimitry Andric   if (TypesInProcessing.count(Ty) && !Ty->isPointerTy())
734fcaf7f86SDimitry Andric     return nullptr;
735fcaf7f86SDimitry Andric   TypesInProcessing.insert(Ty);
736fcaf7f86SDimitry Andric   SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
737fcaf7f86SDimitry Andric   TypesInProcessing.erase(Ty);
738fcaf7f86SDimitry Andric   VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
739fcaf7f86SDimitry Andric   SPIRVToLLVMType[SpirvType] = Ty;
740fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
741fcaf7f86SDimitry Andric   // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
742fcaf7f86SDimitry Andric   // will be added later. For special types it is already added to DT.
743fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
7445f757f3fSDimitry Andric       !isSpecialOpaqueType(Ty)) {
7455f757f3fSDimitry Andric     if (!Ty->isPointerTy())
746fcaf7f86SDimitry Andric       DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
7475f757f3fSDimitry Andric     else
7485f757f3fSDimitry Andric       DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
7495f757f3fSDimitry Andric              Ty->getPointerAddressSpace(), &MIRBuilder.getMF(),
7505f757f3fSDimitry Andric              getSPIRVTypeID(SpirvType));
7515f757f3fSDimitry Andric   }
752fcaf7f86SDimitry Andric 
753fcaf7f86SDimitry Andric   return SpirvType;
754fcaf7f86SDimitry Andric }
755fcaf7f86SDimitry Andric 
75681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg) const {
75781ad6265SDimitry Andric   auto t = VRegToTypeMap.find(CurMF);
75881ad6265SDimitry Andric   if (t != VRegToTypeMap.end()) {
75981ad6265SDimitry Andric     auto tt = t->second.find(VReg);
76081ad6265SDimitry Andric     if (tt != t->second.end())
76181ad6265SDimitry Andric       return tt->second;
76281ad6265SDimitry Andric   }
76381ad6265SDimitry Andric   return nullptr;
76481ad6265SDimitry Andric }
76581ad6265SDimitry Andric 
76681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
767fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
768bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
7695f757f3fSDimitry Andric   Register Reg;
7705f757f3fSDimitry Andric   if (!Ty->isPointerTy())
7715f757f3fSDimitry Andric     Reg = DT.find(Ty, &MIRBuilder.getMF());
7725f757f3fSDimitry Andric   else
7735f757f3fSDimitry Andric     Reg =
7745f757f3fSDimitry Andric         DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),
7755f757f3fSDimitry Andric                 Ty->getPointerAddressSpace(), &MIRBuilder.getMF());
7765f757f3fSDimitry Andric 
777bdd1243dSDimitry Andric   if (Reg.isValid() && !isSpecialOpaqueType(Ty))
778753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
779fcaf7f86SDimitry Andric   TypesInProcessing.clear();
780fcaf7f86SDimitry Andric   SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
781fcaf7f86SDimitry Andric   // Create normal pointer types for the corresponding OpTypeForwardPointers.
782fcaf7f86SDimitry Andric   for (auto &CU : ForwardPointerTypes) {
783fcaf7f86SDimitry Andric     const Type *Ty2 = CU.first;
784fcaf7f86SDimitry Andric     SPIRVType *STy2 = CU.second;
785fcaf7f86SDimitry Andric     if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
786fcaf7f86SDimitry Andric       STy2 = getSPIRVTypeForVReg(Reg);
787fcaf7f86SDimitry Andric     else
788fcaf7f86SDimitry Andric       STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
789fcaf7f86SDimitry Andric     if (Ty == Ty2)
790fcaf7f86SDimitry Andric       STy = STy2;
791fcaf7f86SDimitry Andric   }
792fcaf7f86SDimitry Andric   ForwardPointerTypes.clear();
793fcaf7f86SDimitry Andric   return STy;
79481ad6265SDimitry Andric }
79581ad6265SDimitry Andric 
79681ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOfType(Register VReg,
79781ad6265SDimitry Andric                                          unsigned TypeOpcode) const {
79881ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
79981ad6265SDimitry Andric   assert(Type && "isScalarOfType VReg has no type assigned");
80081ad6265SDimitry Andric   return Type->getOpcode() == TypeOpcode;
80181ad6265SDimitry Andric }
80281ad6265SDimitry Andric 
80381ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg,
80481ad6265SDimitry Andric                                                  unsigned TypeOpcode) const {
80581ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
80681ad6265SDimitry Andric   assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
80781ad6265SDimitry Andric   if (Type->getOpcode() == TypeOpcode)
80881ad6265SDimitry Andric     return true;
80981ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
81081ad6265SDimitry Andric     Register ScalarTypeVReg = Type->getOperand(1).getReg();
81181ad6265SDimitry Andric     SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
81281ad6265SDimitry Andric     return ScalarType->getOpcode() == TypeOpcode;
81381ad6265SDimitry Andric   }
81481ad6265SDimitry Andric   return false;
81581ad6265SDimitry Andric }
81681ad6265SDimitry Andric 
81781ad6265SDimitry Andric unsigned
81881ad6265SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorBitWidth(const SPIRVType *Type) const {
81981ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
82081ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
82181ad6265SDimitry Andric     auto EleTypeReg = Type->getOperand(1).getReg();
82281ad6265SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
82381ad6265SDimitry Andric   }
82481ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeInt ||
82581ad6265SDimitry Andric       Type->getOpcode() == SPIRV::OpTypeFloat)
82681ad6265SDimitry Andric     return Type->getOperand(1).getImm();
82781ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeBool)
82881ad6265SDimitry Andric     return 1;
82981ad6265SDimitry Andric   llvm_unreachable("Attempting to get bit width of non-integer/float type.");
83081ad6265SDimitry Andric }
83181ad6265SDimitry Andric 
83281ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorSigned(const SPIRVType *Type) const {
83381ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
83481ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
83581ad6265SDimitry Andric     auto EleTypeReg = Type->getOperand(1).getReg();
83681ad6265SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
83781ad6265SDimitry Andric   }
83881ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeInt)
83981ad6265SDimitry Andric     return Type->getOperand(2).getImm() != 0;
84081ad6265SDimitry Andric   llvm_unreachable("Attempting to get sign of non-integer type.");
84181ad6265SDimitry Andric }
84281ad6265SDimitry Andric 
843bdd1243dSDimitry Andric SPIRV::StorageClass::StorageClass
84481ad6265SDimitry Andric SPIRVGlobalRegistry::getPointerStorageClass(Register VReg) const {
84581ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
84681ad6265SDimitry Andric   assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
84781ad6265SDimitry Andric          Type->getOperand(1).isImm() && "Pointer type is expected");
848bdd1243dSDimitry Andric   return static_cast<SPIRV::StorageClass::StorageClass>(
849bdd1243dSDimitry Andric       Type->getOperand(1).getImm());
850bdd1243dSDimitry Andric }
851bdd1243dSDimitry Andric 
852bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
853bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
854bdd1243dSDimitry Andric     uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
855bdd1243dSDimitry Andric     SPIRV::ImageFormat::ImageFormat ImageFormat,
856bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
857bdd1243dSDimitry Andric   SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
858bdd1243dSDimitry Andric                                 Arrayed, Multisampled, Sampled, ImageFormat,
859bdd1243dSDimitry Andric                                 AccessQual);
860bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
861bdd1243dSDimitry Andric     return Res;
862bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
863bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
864bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
865bdd1243dSDimitry Andric       .addDef(ResVReg)
866bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(SampledType))
867bdd1243dSDimitry Andric       .addImm(Dim)
868bdd1243dSDimitry Andric       .addImm(Depth)        // Depth (whether or not it is a Depth image).
869bdd1243dSDimitry Andric       .addImm(Arrayed)      // Arrayed.
870bdd1243dSDimitry Andric       .addImm(Multisampled) // Multisampled (0 = only single-sample).
871bdd1243dSDimitry Andric       .addImm(Sampled)      // Sampled (0 = usage known at runtime).
872bdd1243dSDimitry Andric       .addImm(ImageFormat)
873bdd1243dSDimitry Andric       .addImm(AccessQual);
874bdd1243dSDimitry Andric }
875bdd1243dSDimitry Andric 
876bdd1243dSDimitry Andric SPIRVType *
877bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
878bdd1243dSDimitry Andric   SPIRV::SamplerTypeDescriptor TD;
879bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
880bdd1243dSDimitry Andric     return Res;
881bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
882bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
883bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
884bdd1243dSDimitry Andric }
885bdd1243dSDimitry Andric 
886bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
887bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder,
888bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
889bdd1243dSDimitry Andric   SPIRV::PipeTypeDescriptor TD(AccessQual);
890bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
891bdd1243dSDimitry Andric     return Res;
892bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
893bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
894bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
895bdd1243dSDimitry Andric       .addDef(ResVReg)
896bdd1243dSDimitry Andric       .addImm(AccessQual);
897bdd1243dSDimitry Andric }
898bdd1243dSDimitry Andric 
899bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
900bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder) {
901bdd1243dSDimitry Andric   SPIRV::DeviceEventTypeDescriptor TD;
902bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
903bdd1243dSDimitry Andric     return Res;
904bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
905bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
906bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
907bdd1243dSDimitry Andric }
908bdd1243dSDimitry Andric 
909bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(
910bdd1243dSDimitry Andric     SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
911bdd1243dSDimitry Andric   SPIRV::SampledImageTypeDescriptor TD(
912bdd1243dSDimitry Andric       SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
913bdd1243dSDimitry Andric           ImageType->getOperand(1).getReg())),
914bdd1243dSDimitry Andric       ImageType);
915bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
916bdd1243dSDimitry Andric     return Res;
917bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
918bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
919bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
920bdd1243dSDimitry Andric       .addDef(ResVReg)
921bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(ImageType));
922bdd1243dSDimitry Andric }
923bdd1243dSDimitry Andric 
924bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(
925bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
926bdd1243dSDimitry Andric   Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
927bdd1243dSDimitry Andric   if (ResVReg.isValid())
928bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
929bdd1243dSDimitry Andric   ResVReg = createTypeVReg(MIRBuilder);
9305f757f3fSDimitry Andric   SPIRVType *SpirvTy = MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
931bdd1243dSDimitry Andric   DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
9325f757f3fSDimitry Andric   return SpirvTy;
933bdd1243dSDimitry Andric }
934bdd1243dSDimitry Andric 
935bdd1243dSDimitry Andric const MachineInstr *
936bdd1243dSDimitry Andric SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
937bdd1243dSDimitry Andric                                        MachineIRBuilder &MIRBuilder) {
938bdd1243dSDimitry Andric   Register Reg = DT.find(TD, &MIRBuilder.getMF());
939bdd1243dSDimitry Andric   if (Reg.isValid())
940bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
941bdd1243dSDimitry Andric   return nullptr;
942bdd1243dSDimitry Andric }
943bdd1243dSDimitry Andric 
944bdd1243dSDimitry Andric // TODO: maybe use tablegen to implement this.
9455f757f3fSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(
9465f757f3fSDimitry Andric     StringRef TypeStr, MachineIRBuilder &MIRBuilder,
9475f757f3fSDimitry Andric     SPIRV::StorageClass::StorageClass SC,
9485f757f3fSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AQ) {
949bdd1243dSDimitry Andric   unsigned VecElts = 0;
950bdd1243dSDimitry Andric   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
951bdd1243dSDimitry Andric 
9525f757f3fSDimitry Andric   // Parse strings representing either a SPIR-V or OpenCL builtin type.
9535f757f3fSDimitry Andric   if (hasBuiltinTypePrefix(TypeStr))
9545f757f3fSDimitry Andric     return getOrCreateSPIRVType(
9555f757f3fSDimitry Andric         SPIRV::parseBuiltinTypeNameToTargetExtType(TypeStr.str(), MIRBuilder),
9565f757f3fSDimitry Andric         MIRBuilder, AQ);
9575f757f3fSDimitry Andric 
958bdd1243dSDimitry Andric   // Parse type name in either "typeN" or "type vector[N]" format, where
959bdd1243dSDimitry Andric   // N is the number of elements of the vector.
9605f757f3fSDimitry Andric   Type *Ty;
9615f757f3fSDimitry Andric 
9625f757f3fSDimitry Andric   if (TypeStr.starts_with("atomic_"))
9635f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("atomic_"));
9645f757f3fSDimitry Andric 
9655f757f3fSDimitry Andric   if (TypeStr.starts_with("void")) {
9665f757f3fSDimitry Andric     Ty = Type::getVoidTy(Ctx);
967bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen("void"));
9685f757f3fSDimitry Andric   } else if (TypeStr.starts_with("bool")) {
9695f757f3fSDimitry Andric     Ty = Type::getIntNTy(Ctx, 1);
9705f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("bool"));
9715f757f3fSDimitry Andric   } else if (TypeStr.starts_with("char") || TypeStr.starts_with("uchar")) {
9725f757f3fSDimitry Andric     Ty = Type::getInt8Ty(Ctx);
9735f757f3fSDimitry Andric     TypeStr = TypeStr.starts_with("char") ? TypeStr.substr(strlen("char"))
9745f757f3fSDimitry Andric                                           : TypeStr.substr(strlen("uchar"));
9755f757f3fSDimitry Andric   } else if (TypeStr.starts_with("short") || TypeStr.starts_with("ushort")) {
9765f757f3fSDimitry Andric     Ty = Type::getInt16Ty(Ctx);
9775f757f3fSDimitry Andric     TypeStr = TypeStr.starts_with("short") ? TypeStr.substr(strlen("short"))
9785f757f3fSDimitry Andric                                            : TypeStr.substr(strlen("ushort"));
9795f757f3fSDimitry Andric   } else if (TypeStr.starts_with("int") || TypeStr.starts_with("uint")) {
9805f757f3fSDimitry Andric     Ty = Type::getInt32Ty(Ctx);
9815f757f3fSDimitry Andric     TypeStr = TypeStr.starts_with("int") ? TypeStr.substr(strlen("int"))
982bdd1243dSDimitry Andric                                          : TypeStr.substr(strlen("uint"));
9835f757f3fSDimitry Andric   } else if (TypeStr.starts_with("long") || TypeStr.starts_with("ulong")) {
9845f757f3fSDimitry Andric     Ty = Type::getInt64Ty(Ctx);
9855f757f3fSDimitry Andric     TypeStr = TypeStr.starts_with("long") ? TypeStr.substr(strlen("long"))
9865f757f3fSDimitry Andric                                           : TypeStr.substr(strlen("ulong"));
9875f757f3fSDimitry Andric   } else if (TypeStr.starts_with("half")) {
9885f757f3fSDimitry Andric     Ty = Type::getHalfTy(Ctx);
989bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen("half"));
9905f757f3fSDimitry Andric   } else if (TypeStr.starts_with("float")) {
9915f757f3fSDimitry Andric     Ty = Type::getFloatTy(Ctx);
9925f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("float"));
9935f757f3fSDimitry Andric   } else if (TypeStr.starts_with("double")) {
9945f757f3fSDimitry Andric     Ty = Type::getDoubleTy(Ctx);
9955f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("double"));
996bdd1243dSDimitry Andric   } else
997bdd1243dSDimitry Andric     llvm_unreachable("Unable to recognize SPIRV type name.");
9985f757f3fSDimitry Andric 
9995f757f3fSDimitry Andric   auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
10005f757f3fSDimitry Andric 
10015f757f3fSDimitry Andric   // Handle "type*" or  "type* vector[N]".
10025f757f3fSDimitry Andric   if (TypeStr.starts_with("*")) {
10035f757f3fSDimitry Andric     SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
10045f757f3fSDimitry Andric     TypeStr = TypeStr.substr(strlen("*"));
10055f757f3fSDimitry Andric   }
10065f757f3fSDimitry Andric 
10075f757f3fSDimitry Andric   // Handle "typeN*" or  "type vector[N]*".
10085f757f3fSDimitry Andric   bool IsPtrToVec = TypeStr.consume_back("*");
10095f757f3fSDimitry Andric 
10105f757f3fSDimitry Andric   if (TypeStr.starts_with(" vector[")) {
1011bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen(" vector["));
1012bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(0, TypeStr.find(']'));
1013bdd1243dSDimitry Andric   }
1014bdd1243dSDimitry Andric   TypeStr.getAsInteger(10, VecElts);
1015bdd1243dSDimitry Andric   if (VecElts > 0)
1016bdd1243dSDimitry Andric     SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
10175f757f3fSDimitry Andric 
10185f757f3fSDimitry Andric   if (IsPtrToVec)
10195f757f3fSDimitry Andric     SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
10205f757f3fSDimitry Andric 
1021bdd1243dSDimitry Andric   return SpirvTy;
102281ad6265SDimitry Andric }
102381ad6265SDimitry Andric 
102481ad6265SDimitry Andric SPIRVType *
102581ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(unsigned BitWidth,
102681ad6265SDimitry Andric                                                  MachineIRBuilder &MIRBuilder) {
102781ad6265SDimitry Andric   return getOrCreateSPIRVType(
102881ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), BitWidth),
102981ad6265SDimitry Andric       MIRBuilder);
103081ad6265SDimitry Andric }
103181ad6265SDimitry Andric 
1032fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
1033753f127fSDimitry Andric                                                         SPIRVType *SpirvType) {
1034753f127fSDimitry Andric   assert(CurMF == SpirvType->getMF());
103581ad6265SDimitry Andric   VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
103681ad6265SDimitry Andric   SPIRVToLLVMType[SpirvType] = LLVMTy;
103781ad6265SDimitry Andric   return SpirvType;
103881ad6265SDimitry Andric }
103981ad6265SDimitry Andric 
104081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(
104181ad6265SDimitry Andric     unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
104281ad6265SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);
1043753f127fSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1044753f127fSDimitry Andric   if (Reg.isValid())
1045753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
104681ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
104781ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeInt))
104881ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
104981ad6265SDimitry Andric                  .addImm(BitWidth)
105081ad6265SDimitry Andric                  .addImm(0);
10515f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1052fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
105381ad6265SDimitry Andric }
105481ad6265SDimitry Andric 
105581ad6265SDimitry Andric SPIRVType *
105681ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder) {
105781ad6265SDimitry Andric   return getOrCreateSPIRVType(
105881ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
105981ad6265SDimitry Andric       MIRBuilder);
106081ad6265SDimitry Andric }
106181ad6265SDimitry Andric 
1062fcaf7f86SDimitry Andric SPIRVType *
1063fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
1064fcaf7f86SDimitry Andric                                               const SPIRVInstrInfo &TII) {
1065fcaf7f86SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), 1);
1066fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1067fcaf7f86SDimitry Andric   if (Reg.isValid())
1068fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
1069fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1070fcaf7f86SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
1071fcaf7f86SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()));
10725f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1073fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1074fcaf7f86SDimitry Andric }
1075fcaf7f86SDimitry Andric 
107681ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
107781ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
107881ad6265SDimitry Andric   return getOrCreateSPIRVType(
107981ad6265SDimitry Andric       FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
108081ad6265SDimitry Andric                            NumElements),
108181ad6265SDimitry Andric       MIRBuilder);
108281ad6265SDimitry Andric }
108381ad6265SDimitry Andric 
108481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
108581ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
108681ad6265SDimitry Andric     const SPIRVInstrInfo &TII) {
108781ad6265SDimitry Andric   Type *LLVMTy = FixedVectorType::get(
108881ad6265SDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1089fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1090fcaf7f86SDimitry Andric   if (Reg.isValid())
1091fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
109281ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
109381ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
109481ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
109581ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
109681ad6265SDimitry Andric                  .addImm(NumElements);
10975f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1098fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
109981ad6265SDimitry Andric }
110081ad6265SDimitry Andric 
1101bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
1102bdd1243dSDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1103bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII) {
1104bdd1243dSDimitry Andric   Type *LLVMTy = ArrayType::get(
1105bdd1243dSDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1106bdd1243dSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1107bdd1243dSDimitry Andric   if (Reg.isValid())
1108bdd1243dSDimitry Andric     return getSPIRVTypeForVReg(Reg);
1109bdd1243dSDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1110bdd1243dSDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1111bdd1243dSDimitry Andric   Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1112bdd1243dSDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1113bdd1243dSDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
1114bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
1115bdd1243dSDimitry Andric                  .addUse(Len);
11165f757f3fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(MIB));
1117bdd1243dSDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1118bdd1243dSDimitry Andric }
1119bdd1243dSDimitry Andric 
1120bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
1121bdd1243dSDimitry Andric     SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
11225f757f3fSDimitry Andric     SPIRV::StorageClass::StorageClass SC) {
11235f757f3fSDimitry Andric   const Type *PointerElementType = getTypeForSPIRVType(BaseType);
11245f757f3fSDimitry Andric   unsigned AddressSpace = storageClassToAddressSpace(SC);
11255f757f3fSDimitry Andric   Type *LLVMTy =
11265f757f3fSDimitry Andric       PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
11275f757f3fSDimitry Andric   Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
11285f757f3fSDimitry Andric   if (Reg.isValid())
11295f757f3fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
11305f757f3fSDimitry Andric   auto MIB = BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),
11315f757f3fSDimitry Andric                      MIRBuilder.getDebugLoc(),
11325f757f3fSDimitry Andric                      MIRBuilder.getTII().get(SPIRV::OpTypePointer))
11335f757f3fSDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
11345f757f3fSDimitry Andric                  .addImm(static_cast<uint32_t>(SC))
11355f757f3fSDimitry Andric                  .addUse(getSPIRVTypeID(BaseType));
11365f757f3fSDimitry Andric   DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
11375f757f3fSDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
113881ad6265SDimitry Andric }
113981ad6265SDimitry Andric 
114081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
114181ad6265SDimitry Andric     SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &TII,
1142bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC) {
11435f757f3fSDimitry Andric   const Type *PointerElementType = getTypeForSPIRVType(BaseType);
11445f757f3fSDimitry Andric   unsigned AddressSpace = storageClassToAddressSpace(SC);
114581ad6265SDimitry Andric   Type *LLVMTy =
11465f757f3fSDimitry Andric       PointerType::get(const_cast<Type *>(PointerElementType), AddressSpace);
11475f757f3fSDimitry Andric   Register Reg = DT.find(PointerElementType, AddressSpace, CurMF);
1148fcaf7f86SDimitry Andric   if (Reg.isValid())
1149fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
115081ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
115181ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypePointer))
115281ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
115381ad6265SDimitry Andric                  .addImm(static_cast<uint32_t>(SC))
115481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType));
11555f757f3fSDimitry Andric   DT.add(PointerElementType, AddressSpace, CurMF, getSPIRVTypeID(MIB));
1156fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1157fcaf7f86SDimitry Andric }
1158fcaf7f86SDimitry Andric 
1159fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
1160fcaf7f86SDimitry Andric                                                SPIRVType *SpvType,
1161fcaf7f86SDimitry Andric                                                const SPIRVInstrInfo &TII) {
1162fcaf7f86SDimitry Andric   assert(SpvType);
1163fcaf7f86SDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1164fcaf7f86SDimitry Andric   assert(LLVMTy);
1165fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
1166fcaf7f86SDimitry Andric   UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1167fcaf7f86SDimitry Andric   Register Res = DT.find(UV, CurMF);
1168fcaf7f86SDimitry Andric   if (Res.isValid())
1169fcaf7f86SDimitry Andric     return Res;
1170fcaf7f86SDimitry Andric   LLT LLTy = LLT::scalar(32);
1171fcaf7f86SDimitry Andric   Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
117206c3fb27SDimitry Andric   CurMF->getRegInfo().setRegClass(Res, &SPIRV::IDRegClass);
1173fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1174fcaf7f86SDimitry Andric   DT.add(UV, CurMF, Res);
1175fcaf7f86SDimitry Andric 
1176fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
1177fcaf7f86SDimitry Andric   MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1178fcaf7f86SDimitry Andric             .addDef(Res)
1179fcaf7f86SDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
1180fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
1181fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1182fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
1183fcaf7f86SDimitry Andric   return Res;
118481ad6265SDimitry Andric }
1185