xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
19*bdd1243dSDimitry 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,
48*bdd1243dSDimitry 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) {
8381ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt)
8481ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
8581ad6265SDimitry Andric                  .addImm(Width)
8681ad6265SDimitry Andric                  .addImm(IsSigned ? 1 : 0);
8781ad6265SDimitry Andric   return MIB;
8881ad6265SDimitry Andric }
8981ad6265SDimitry Andric 
9081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,
9181ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder) {
9281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFloat)
9381ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
9481ad6265SDimitry Andric                  .addImm(Width);
9581ad6265SDimitry Andric   return MIB;
9681ad6265SDimitry Andric }
9781ad6265SDimitry Andric 
9881ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
9981ad6265SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
10081ad6265SDimitry Andric       .addDef(createTypeVReg(MIRBuilder));
10181ad6265SDimitry Andric }
10281ad6265SDimitry Andric 
10381ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
10481ad6265SDimitry Andric                                                 SPIRVType *ElemType,
10581ad6265SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
10681ad6265SDimitry Andric   auto EleOpc = ElemType->getOpcode();
10781ad6265SDimitry Andric   assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
10881ad6265SDimitry Andric           EleOpc == SPIRV::OpTypeBool) &&
10981ad6265SDimitry Andric          "Invalid vector element type");
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeVector)
11281ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
11381ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
11481ad6265SDimitry Andric                  .addImm(NumElems);
11581ad6265SDimitry Andric   return MIB;
11681ad6265SDimitry Andric }
11781ad6265SDimitry Andric 
118fcaf7f86SDimitry Andric std::tuple<Register, ConstantInt *, bool>
119fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateConstIntReg(uint64_t Val, SPIRVType *SpvType,
120fcaf7f86SDimitry Andric                                             MachineIRBuilder *MIRBuilder,
121fcaf7f86SDimitry Andric                                             MachineInstr *I,
122fcaf7f86SDimitry Andric                                             const SPIRVInstrInfo *TII) {
123fcaf7f86SDimitry Andric   const IntegerType *LLVMIntTy;
124fcaf7f86SDimitry Andric   if (SpvType)
125fcaf7f86SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
126fcaf7f86SDimitry Andric   else
127fcaf7f86SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(CurMF->getFunction().getContext());
128fcaf7f86SDimitry Andric   bool NewInstr = false;
129fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
130fcaf7f86SDimitry Andric   ConstantInt *CI = ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
131fcaf7f86SDimitry Andric   Register Res = DT.find(CI, CurMF);
132fcaf7f86SDimitry Andric   if (!Res.isValid()) {
133fcaf7f86SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
134fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
135fcaf7f86SDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
136fcaf7f86SDimitry Andric     if (MIRBuilder)
137fcaf7f86SDimitry Andric       assignTypeToVReg(LLVMIntTy, Res, *MIRBuilder);
138fcaf7f86SDimitry Andric     else
139fcaf7f86SDimitry Andric       assignIntTypeToVReg(BitWidth, Res, *I, *TII);
140fcaf7f86SDimitry Andric     DT.add(CI, CurMF, Res);
141fcaf7f86SDimitry Andric     NewInstr = true;
142fcaf7f86SDimitry Andric   }
143fcaf7f86SDimitry Andric   return std::make_tuple(Res, CI, NewInstr);
144fcaf7f86SDimitry Andric }
145fcaf7f86SDimitry Andric 
146fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,
147fcaf7f86SDimitry Andric                                                   SPIRVType *SpvType,
148fcaf7f86SDimitry Andric                                                   const SPIRVInstrInfo &TII) {
149fcaf7f86SDimitry Andric   assert(SpvType);
150fcaf7f86SDimitry Andric   ConstantInt *CI;
151fcaf7f86SDimitry Andric   Register Res;
152fcaf7f86SDimitry Andric   bool New;
153fcaf7f86SDimitry Andric   std::tie(Res, CI, New) =
154fcaf7f86SDimitry Andric       getOrCreateConstIntReg(Val, SpvType, nullptr, &I, &TII);
155fcaf7f86SDimitry Andric   // If we have found Res register which is defined by the passed G_CONSTANT
156fcaf7f86SDimitry Andric   // machine instruction, a new constant instruction should be created.
157fcaf7f86SDimitry Andric   if (!New && (!I.getOperand(0).isReg() || Res != I.getOperand(0).getReg()))
158fcaf7f86SDimitry Andric     return Res;
159fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
160fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
161fcaf7f86SDimitry Andric   if (Val) {
162fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
163fcaf7f86SDimitry Andric               .addDef(Res)
164fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
165fcaf7f86SDimitry Andric     addNumImm(APInt(getScalarOrVectorBitWidth(SpvType), Val), MIB);
166fcaf7f86SDimitry Andric   } else {
167fcaf7f86SDimitry Andric     MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
168fcaf7f86SDimitry Andric               .addDef(Res)
169fcaf7f86SDimitry Andric               .addUse(getSPIRVTypeID(SpvType));
170fcaf7f86SDimitry Andric   }
171fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
172fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
173fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
174fcaf7f86SDimitry Andric   return Res;
175fcaf7f86SDimitry Andric }
176fcaf7f86SDimitry Andric 
17781ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,
17881ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
17981ad6265SDimitry Andric                                                SPIRVType *SpvType,
18081ad6265SDimitry Andric                                                bool EmitIR) {
18181ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
18281ad6265SDimitry Andric   const IntegerType *LLVMIntTy;
18381ad6265SDimitry Andric   if (SpvType)
18481ad6265SDimitry Andric     LLVMIntTy = cast<IntegerType>(getTypeForSPIRVType(SpvType));
18581ad6265SDimitry Andric   else
18681ad6265SDimitry Andric     LLVMIntTy = IntegerType::getInt32Ty(MF.getFunction().getContext());
18781ad6265SDimitry Andric   // Find a constant in DT or build a new one.
18881ad6265SDimitry Andric   const auto ConstInt =
18981ad6265SDimitry Andric       ConstantInt::get(const_cast<IntegerType *>(LLVMIntTy), Val);
190753f127fSDimitry Andric   Register Res = DT.find(ConstInt, &MF);
191753f127fSDimitry Andric   if (!Res.isValid()) {
19281ad6265SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
193fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(EmitIR ? BitWidth : 32);
194fcaf7f86SDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);
195fcaf7f86SDimitry Andric     assignTypeToVReg(LLVMIntTy, Res, MIRBuilder,
196fcaf7f86SDimitry Andric                      SPIRV::AccessQualifier::ReadWrite, EmitIR);
197fcaf7f86SDimitry Andric     DT.add(ConstInt, &MIRBuilder.getMF(), Res);
198fcaf7f86SDimitry Andric     if (EmitIR) {
19981ad6265SDimitry Andric       MIRBuilder.buildConstant(Res, *ConstInt);
200fcaf7f86SDimitry Andric     } else {
201fcaf7f86SDimitry Andric       MachineInstrBuilder MIB;
202fcaf7f86SDimitry Andric       if (Val) {
203fcaf7f86SDimitry Andric         assert(SpvType);
204fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)
20581ad6265SDimitry Andric                   .addDef(Res)
206fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
207fcaf7f86SDimitry Andric         addNumImm(APInt(BitWidth, Val), MIB);
208fcaf7f86SDimitry Andric       } else {
209fcaf7f86SDimitry Andric         assert(SpvType);
210fcaf7f86SDimitry Andric         MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)
211fcaf7f86SDimitry Andric                   .addDef(Res)
212fcaf7f86SDimitry Andric                   .addUse(getSPIRVTypeID(SpvType));
213fcaf7f86SDimitry Andric       }
214fcaf7f86SDimitry Andric       const auto &Subtarget = CurMF->getSubtarget();
215fcaf7f86SDimitry Andric       constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
216fcaf7f86SDimitry Andric                                        *Subtarget.getRegisterInfo(),
217fcaf7f86SDimitry Andric                                        *Subtarget.getRegBankInfo());
218fcaf7f86SDimitry Andric     }
219753f127fSDimitry Andric   }
22081ad6265SDimitry Andric   return Res;
22181ad6265SDimitry Andric }
22281ad6265SDimitry Andric 
22381ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,
22481ad6265SDimitry Andric                                               MachineIRBuilder &MIRBuilder,
22581ad6265SDimitry Andric                                               SPIRVType *SpvType) {
22681ad6265SDimitry Andric   auto &MF = MIRBuilder.getMF();
22781ad6265SDimitry Andric   const Type *LLVMFPTy;
22881ad6265SDimitry Andric   if (SpvType) {
22981ad6265SDimitry Andric     LLVMFPTy = getTypeForSPIRVType(SpvType);
23081ad6265SDimitry Andric     assert(LLVMFPTy->isFloatingPointTy());
23181ad6265SDimitry Andric   } else {
23281ad6265SDimitry Andric     LLVMFPTy = IntegerType::getFloatTy(MF.getFunction().getContext());
23381ad6265SDimitry Andric   }
23481ad6265SDimitry Andric   // Find a constant in DT or build a new one.
23581ad6265SDimitry Andric   const auto ConstFP = ConstantFP::get(LLVMFPTy->getContext(), Val);
236753f127fSDimitry Andric   Register Res = DT.find(ConstFP, &MF);
237753f127fSDimitry Andric   if (!Res.isValid()) {
23881ad6265SDimitry Andric     unsigned BitWidth = SpvType ? getScalarOrVectorBitWidth(SpvType) : 32;
23981ad6265SDimitry Andric     Res = MF.getRegInfo().createGenericVirtualRegister(LLT::scalar(BitWidth));
24081ad6265SDimitry Andric     assignTypeToVReg(LLVMFPTy, Res, MIRBuilder);
241fcaf7f86SDimitry Andric     DT.add(ConstFP, &MF, Res);
24281ad6265SDimitry Andric     MIRBuilder.buildFConstant(Res, *ConstFP);
243753f127fSDimitry Andric   }
24481ad6265SDimitry Andric   return Res;
24581ad6265SDimitry Andric }
24681ad6265SDimitry Andric 
247*bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
248*bdd1243dSDimitry Andric     uint64_t Val, MachineInstr &I, SPIRVType *SpvType,
249*bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,
250*bdd1243dSDimitry Andric     unsigned ElemCnt) {
251fcaf7f86SDimitry Andric   // Find a constant vector in DT or build a new one.
252*bdd1243dSDimitry Andric   Register Res = DT.find(CA, CurMF);
253fcaf7f86SDimitry Andric   if (!Res.isValid()) {
254fcaf7f86SDimitry Andric     SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);
255fcaf7f86SDimitry Andric     // SpvScalConst should be created before SpvVecConst to avoid undefined ID
256fcaf7f86SDimitry Andric     // error on validation.
257fcaf7f86SDimitry Andric     // TODO: can moved below once sorting of types/consts/defs is implemented.
258fcaf7f86SDimitry Andric     Register SpvScalConst;
259fcaf7f86SDimitry Andric     if (Val)
260fcaf7f86SDimitry Andric       SpvScalConst = getOrCreateConstInt(Val, I, SpvBaseType, TII);
261fcaf7f86SDimitry Andric     // TODO: maybe use bitwidth of base type.
262fcaf7f86SDimitry Andric     LLT LLTy = LLT::scalar(32);
263fcaf7f86SDimitry Andric     Register SpvVecConst =
264fcaf7f86SDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
265*bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
266*bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
267fcaf7f86SDimitry Andric     MachineInstrBuilder MIB;
268fcaf7f86SDimitry Andric     MachineBasicBlock &BB = *I.getParent();
269fcaf7f86SDimitry Andric     if (Val) {
270fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantComposite))
271fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
272fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
273fcaf7f86SDimitry Andric       for (unsigned i = 0; i < ElemCnt; ++i)
274fcaf7f86SDimitry Andric         MIB.addUse(SpvScalConst);
275fcaf7f86SDimitry Andric     } else {
276fcaf7f86SDimitry Andric       MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
277fcaf7f86SDimitry Andric                 .addDef(SpvVecConst)
278fcaf7f86SDimitry Andric                 .addUse(getSPIRVTypeID(SpvType));
279fcaf7f86SDimitry Andric     }
280fcaf7f86SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
281fcaf7f86SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
282fcaf7f86SDimitry Andric                                      *Subtarget.getRegisterInfo(),
283fcaf7f86SDimitry Andric                                      *Subtarget.getRegBankInfo());
284fcaf7f86SDimitry Andric     return SpvVecConst;
285fcaf7f86SDimitry Andric   }
286fcaf7f86SDimitry Andric   return Res;
287fcaf7f86SDimitry Andric }
288fcaf7f86SDimitry Andric 
289*bdd1243dSDimitry Andric Register
290*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val, MachineInstr &I,
291*bdd1243dSDimitry Andric                                               SPIRVType *SpvType,
292*bdd1243dSDimitry Andric                                               const SPIRVInstrInfo &TII) {
293*bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
294*bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
295*bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
296*bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
297*bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
298*bdd1243dSDimitry Andric   auto ConstVec =
299*bdd1243dSDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
300*bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
301*bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstVec, BW,
302*bdd1243dSDimitry Andric                                        SpvType->getOperand(2).getImm());
303*bdd1243dSDimitry Andric }
304*bdd1243dSDimitry Andric 
305*bdd1243dSDimitry Andric Register
306*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntArray(uint64_t Val, MachineInstr &I,
307*bdd1243dSDimitry Andric                                              SPIRVType *SpvType,
308*bdd1243dSDimitry Andric                                              const SPIRVInstrInfo &TII) {
309*bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
310*bdd1243dSDimitry Andric   assert(LLVMTy->isArrayTy());
311*bdd1243dSDimitry Andric   const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
312*bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMArrTy->getElementType();
313*bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
314*bdd1243dSDimitry Andric   auto ConstArr =
315*bdd1243dSDimitry Andric       ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
316*bdd1243dSDimitry Andric   SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
317*bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
318*bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, I, SpvType, TII, ConstArr, BW,
319*bdd1243dSDimitry Andric                                        LLVMArrTy->getNumElements());
320*bdd1243dSDimitry Andric }
321*bdd1243dSDimitry Andric 
322*bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(
323*bdd1243dSDimitry Andric     uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,
324*bdd1243dSDimitry Andric     Constant *CA, unsigned BitWidth, unsigned ElemCnt) {
325*bdd1243dSDimitry Andric   Register Res = DT.find(CA, CurMF);
326*bdd1243dSDimitry Andric   if (!Res.isValid()) {
327*bdd1243dSDimitry Andric     Register SpvScalConst;
328*bdd1243dSDimitry Andric     if (Val || EmitIR) {
329*bdd1243dSDimitry Andric       SPIRVType *SpvBaseType =
330*bdd1243dSDimitry Andric           getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);
331*bdd1243dSDimitry Andric       SpvScalConst = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);
332*bdd1243dSDimitry Andric     }
333*bdd1243dSDimitry Andric     LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(32);
334*bdd1243dSDimitry Andric     Register SpvVecConst =
335*bdd1243dSDimitry Andric         CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
336*bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, SpvVecConst, *CurMF);
337*bdd1243dSDimitry Andric     DT.add(CA, CurMF, SpvVecConst);
338*bdd1243dSDimitry Andric     if (EmitIR) {
339*bdd1243dSDimitry Andric       MIRBuilder.buildSplatVector(SpvVecConst, SpvScalConst);
340*bdd1243dSDimitry Andric     } else {
341*bdd1243dSDimitry Andric       if (Val) {
342*bdd1243dSDimitry Andric         auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)
343*bdd1243dSDimitry Andric                        .addDef(SpvVecConst)
344*bdd1243dSDimitry Andric                        .addUse(getSPIRVTypeID(SpvType));
345*bdd1243dSDimitry Andric         for (unsigned i = 0; i < ElemCnt; ++i)
346*bdd1243dSDimitry Andric           MIB.addUse(SpvScalConst);
347*bdd1243dSDimitry Andric       } else {
348*bdd1243dSDimitry Andric         MIRBuilder.buildInstr(SPIRV::OpConstantNull)
349*bdd1243dSDimitry Andric             .addDef(SpvVecConst)
350*bdd1243dSDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
351*bdd1243dSDimitry Andric       }
352*bdd1243dSDimitry Andric     }
353*bdd1243dSDimitry Andric     return SpvVecConst;
354*bdd1243dSDimitry Andric   }
355*bdd1243dSDimitry Andric   return Res;
356*bdd1243dSDimitry Andric }
357*bdd1243dSDimitry Andric 
358*bdd1243dSDimitry Andric Register
359*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val,
360*bdd1243dSDimitry Andric                                               MachineIRBuilder &MIRBuilder,
361*bdd1243dSDimitry Andric                                               SPIRVType *SpvType, bool EmitIR) {
362*bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
363*bdd1243dSDimitry Andric   assert(LLVMTy->isVectorTy());
364*bdd1243dSDimitry Andric   const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);
365*bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMVecTy->getElementType();
366*bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
367*bdd1243dSDimitry Andric   auto ConstVec =
368*bdd1243dSDimitry Andric       ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);
369*bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvType);
370*bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
371*bdd1243dSDimitry Andric                                        ConstVec, BW,
372*bdd1243dSDimitry Andric                                        SpvType->getOperand(2).getImm());
373*bdd1243dSDimitry Andric }
374*bdd1243dSDimitry Andric 
375*bdd1243dSDimitry Andric Register
376*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConsIntArray(uint64_t Val,
377*bdd1243dSDimitry Andric                                              MachineIRBuilder &MIRBuilder,
378*bdd1243dSDimitry Andric                                              SPIRVType *SpvType, bool EmitIR) {
379*bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
380*bdd1243dSDimitry Andric   assert(LLVMTy->isArrayTy());
381*bdd1243dSDimitry Andric   const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);
382*bdd1243dSDimitry Andric   Type *LLVMBaseTy = LLVMArrTy->getElementType();
383*bdd1243dSDimitry Andric   const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);
384*bdd1243dSDimitry Andric   auto ConstArr =
385*bdd1243dSDimitry Andric       ConstantArray::get(const_cast<ArrayType *>(LLVMArrTy), {ConstInt});
386*bdd1243dSDimitry Andric   SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());
387*bdd1243dSDimitry Andric   unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);
388*bdd1243dSDimitry Andric   return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,
389*bdd1243dSDimitry Andric                                        ConstArr, BW,
390*bdd1243dSDimitry Andric                                        LLVMArrTy->getNumElements());
391*bdd1243dSDimitry Andric }
392*bdd1243dSDimitry Andric 
393*bdd1243dSDimitry Andric Register
394*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
395*bdd1243dSDimitry Andric                                              SPIRVType *SpvType) {
396*bdd1243dSDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
397*bdd1243dSDimitry Andric   const PointerType *LLVMPtrTy = cast<PointerType>(LLVMTy);
398*bdd1243dSDimitry Andric   // Find a constant in DT or build a new one.
399*bdd1243dSDimitry Andric   Constant *CP = ConstantPointerNull::get(const_cast<PointerType *>(LLVMPtrTy));
400*bdd1243dSDimitry Andric   Register Res = DT.find(CP, CurMF);
401*bdd1243dSDimitry Andric   if (!Res.isValid()) {
402*bdd1243dSDimitry Andric     LLT LLTy = LLT::pointer(LLVMPtrTy->getAddressSpace(), PointerSize);
403*bdd1243dSDimitry Andric     Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
404*bdd1243dSDimitry Andric     assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
405*bdd1243dSDimitry Andric     MIRBuilder.buildInstr(SPIRV::OpConstantNull)
406*bdd1243dSDimitry Andric         .addDef(Res)
407*bdd1243dSDimitry Andric         .addUse(getSPIRVTypeID(SpvType));
408*bdd1243dSDimitry Andric     DT.add(CP, CurMF, Res);
409*bdd1243dSDimitry Andric   }
410*bdd1243dSDimitry Andric   return Res;
411*bdd1243dSDimitry Andric }
412*bdd1243dSDimitry Andric 
413*bdd1243dSDimitry Andric Register SPIRVGlobalRegistry::buildConstantSampler(
414*bdd1243dSDimitry Andric     Register ResReg, unsigned AddrMode, unsigned Param, unsigned FilerMode,
415*bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SpvType) {
416*bdd1243dSDimitry Andric   SPIRVType *SampTy;
417*bdd1243dSDimitry Andric   if (SpvType)
418*bdd1243dSDimitry Andric     SampTy = getOrCreateSPIRVType(getTypeForSPIRVType(SpvType), MIRBuilder);
419*bdd1243dSDimitry Andric   else
420*bdd1243dSDimitry Andric     SampTy = getOrCreateSPIRVTypeByName("opencl.sampler_t", MIRBuilder);
421*bdd1243dSDimitry Andric 
422*bdd1243dSDimitry Andric   auto Sampler =
423*bdd1243dSDimitry Andric       ResReg.isValid()
424*bdd1243dSDimitry Andric           ? ResReg
425*bdd1243dSDimitry Andric           : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
426*bdd1243dSDimitry Andric   auto Res = MIRBuilder.buildInstr(SPIRV::OpConstantSampler)
427*bdd1243dSDimitry Andric                  .addDef(Sampler)
428*bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(SampTy))
429*bdd1243dSDimitry Andric                  .addImm(AddrMode)
430*bdd1243dSDimitry Andric                  .addImm(Param)
431*bdd1243dSDimitry Andric                  .addImm(FilerMode);
432*bdd1243dSDimitry Andric   assert(Res->getOperand(0).isReg());
433*bdd1243dSDimitry Andric   return Res->getOperand(0).getReg();
434*bdd1243dSDimitry Andric }
435*bdd1243dSDimitry Andric 
43681ad6265SDimitry Andric Register SPIRVGlobalRegistry::buildGlobalVariable(
43781ad6265SDimitry Andric     Register ResVReg, SPIRVType *BaseType, StringRef Name,
438*bdd1243dSDimitry Andric     const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
43981ad6265SDimitry Andric     const MachineInstr *Init, bool IsConst, bool HasLinkageTy,
440*bdd1243dSDimitry Andric     SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder,
44181ad6265SDimitry Andric     bool IsInstSelector) {
44281ad6265SDimitry Andric   const GlobalVariable *GVar = nullptr;
44381ad6265SDimitry Andric   if (GV)
44481ad6265SDimitry Andric     GVar = cast<const GlobalVariable>(GV);
44581ad6265SDimitry Andric   else {
44681ad6265SDimitry Andric     // If GV is not passed explicitly, use the name to find or construct
44781ad6265SDimitry Andric     // the global variable.
44881ad6265SDimitry Andric     Module *M = MIRBuilder.getMF().getFunction().getParent();
44981ad6265SDimitry Andric     GVar = M->getGlobalVariable(Name);
45081ad6265SDimitry Andric     if (GVar == nullptr) {
45181ad6265SDimitry Andric       const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.
45281ad6265SDimitry Andric       GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,
45381ad6265SDimitry Andric                                 GlobalValue::ExternalLinkage, nullptr,
45481ad6265SDimitry Andric                                 Twine(Name));
45581ad6265SDimitry Andric     }
45681ad6265SDimitry Andric     GV = GVar;
45781ad6265SDimitry Andric   }
458fcaf7f86SDimitry Andric   Register Reg = DT.find(GVar, &MIRBuilder.getMF());
459fcaf7f86SDimitry Andric   if (Reg.isValid()) {
460fcaf7f86SDimitry Andric     if (Reg != ResVReg)
461fcaf7f86SDimitry Andric       MIRBuilder.buildCopy(ResVReg, Reg);
462fcaf7f86SDimitry Andric     return ResVReg;
463fcaf7f86SDimitry Andric   }
464fcaf7f86SDimitry Andric 
46581ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)
46681ad6265SDimitry Andric                  .addDef(ResVReg)
46781ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
46881ad6265SDimitry Andric                  .addImm(static_cast<uint32_t>(Storage));
46981ad6265SDimitry Andric 
47081ad6265SDimitry Andric   if (Init != 0) {
47181ad6265SDimitry Andric     MIB.addUse(Init->getOperand(0).getReg());
47281ad6265SDimitry Andric   }
47381ad6265SDimitry Andric 
47481ad6265SDimitry Andric   // ISel may introduce a new register on this step, so we need to add it to
47581ad6265SDimitry Andric   // DT and correct its type avoiding fails on the next stage.
47681ad6265SDimitry Andric   if (IsInstSelector) {
47781ad6265SDimitry Andric     const auto &Subtarget = CurMF->getSubtarget();
47881ad6265SDimitry Andric     constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),
47981ad6265SDimitry Andric                                      *Subtarget.getRegisterInfo(),
48081ad6265SDimitry Andric                                      *Subtarget.getRegBankInfo());
48181ad6265SDimitry Andric   }
48281ad6265SDimitry Andric   Reg = MIB->getOperand(0).getReg();
483753f127fSDimitry Andric   DT.add(GVar, &MIRBuilder.getMF(), Reg);
48481ad6265SDimitry Andric 
48581ad6265SDimitry Andric   // Set to Reg the same type as ResVReg has.
48681ad6265SDimitry Andric   auto MRI = MIRBuilder.getMRI();
48781ad6265SDimitry Andric   assert(MRI->getType(ResVReg).isPointer() && "Pointer type is expected");
48881ad6265SDimitry Andric   if (Reg != ResVReg) {
48981ad6265SDimitry Andric     LLT RegLLTy = LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), 32);
49081ad6265SDimitry Andric     MRI->setType(Reg, RegLLTy);
49181ad6265SDimitry Andric     assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());
49281ad6265SDimitry Andric   }
49381ad6265SDimitry Andric 
49481ad6265SDimitry Andric   // If it's a global variable with name, output OpName for it.
49581ad6265SDimitry Andric   if (GVar && GVar->hasName())
49681ad6265SDimitry Andric     buildOpName(Reg, GVar->getName(), MIRBuilder);
49781ad6265SDimitry Andric 
49881ad6265SDimitry Andric   // Output decorations for the GV.
49981ad6265SDimitry Andric   // TODO: maybe move to GenerateDecorations pass.
50081ad6265SDimitry Andric   if (IsConst)
50181ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});
50281ad6265SDimitry Andric 
503*bdd1243dSDimitry Andric   if (GVar && GVar->getAlign().valueOrOne().value() != 1) {
504*bdd1243dSDimitry Andric     unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();
505*bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});
506*bdd1243dSDimitry Andric   }
50781ad6265SDimitry Andric 
50881ad6265SDimitry Andric   if (HasLinkageTy)
50981ad6265SDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
51081ad6265SDimitry Andric                     {static_cast<uint32_t>(LinkageType)}, Name);
511*bdd1243dSDimitry Andric 
512*bdd1243dSDimitry Andric   SPIRV::BuiltIn::BuiltIn BuiltInId;
513*bdd1243dSDimitry Andric   if (getSpirvBuiltInIdByName(Name, BuiltInId))
514*bdd1243dSDimitry Andric     buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,
515*bdd1243dSDimitry Andric                     {static_cast<uint32_t>(BuiltInId)});
516*bdd1243dSDimitry Andric 
51781ad6265SDimitry Andric   return Reg;
51881ad6265SDimitry Andric }
51981ad6265SDimitry Andric 
52081ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
52181ad6265SDimitry Andric                                                SPIRVType *ElemType,
52281ad6265SDimitry Andric                                                MachineIRBuilder &MIRBuilder,
52381ad6265SDimitry Andric                                                bool EmitIR) {
52481ad6265SDimitry Andric   assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&
52581ad6265SDimitry Andric          "Invalid array element type");
52681ad6265SDimitry Andric   Register NumElementsVReg =
52781ad6265SDimitry Andric       buildConstantInt(NumElems, MIRBuilder, nullptr, EmitIR);
52881ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeArray)
52981ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
53081ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(ElemType))
53181ad6265SDimitry Andric                  .addUse(NumElementsVReg);
53281ad6265SDimitry Andric   return MIB;
53381ad6265SDimitry Andric }
53481ad6265SDimitry Andric 
535fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
536fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
537fcaf7f86SDimitry Andric   assert(Ty->hasName());
538fcaf7f86SDimitry Andric   const StringRef Name = Ty->hasName() ? Ty->getName() : "";
539fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
540fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);
541fcaf7f86SDimitry Andric   addStringImm(Name, MIB);
542fcaf7f86SDimitry Andric   buildOpName(ResVReg, Name, MIRBuilder);
543fcaf7f86SDimitry Andric   return MIB;
544fcaf7f86SDimitry Andric }
545fcaf7f86SDimitry Andric 
546fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
547fcaf7f86SDimitry Andric                                                 MachineIRBuilder &MIRBuilder,
548fcaf7f86SDimitry Andric                                                 bool EmitIR) {
549fcaf7f86SDimitry Andric   SmallVector<Register, 4> FieldTypes;
550fcaf7f86SDimitry Andric   for (const auto &Elem : Ty->elements()) {
551fcaf7f86SDimitry Andric     SPIRVType *ElemTy = findSPIRVType(Elem, MIRBuilder);
552fcaf7f86SDimitry Andric     assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
553fcaf7f86SDimitry Andric            "Invalid struct element type");
554fcaf7f86SDimitry Andric     FieldTypes.push_back(getSPIRVTypeID(ElemTy));
555fcaf7f86SDimitry Andric   }
556fcaf7f86SDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
557fcaf7f86SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);
558fcaf7f86SDimitry Andric   for (const auto &Ty : FieldTypes)
559fcaf7f86SDimitry Andric     MIB.addUse(Ty);
560fcaf7f86SDimitry Andric   if (Ty->hasName())
561fcaf7f86SDimitry Andric     buildOpName(ResVReg, Ty->getName(), MIRBuilder);
562fcaf7f86SDimitry Andric   if (Ty->isPacked())
563fcaf7f86SDimitry Andric     buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});
564fcaf7f86SDimitry Andric   return MIB;
565fcaf7f86SDimitry Andric }
566fcaf7f86SDimitry Andric 
567*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
568*bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
569*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual) {
570*bdd1243dSDimitry Andric   // Some OpenCL and SPIRV builtins like image2d_t are passed in as
571*bdd1243dSDimitry Andric   // pointers, but should be treated as custom types like OpTypeImage.
572fcaf7f86SDimitry Andric   if (auto PType = dyn_cast<PointerType>(Ty)) {
573*bdd1243dSDimitry Andric     assert(!PType->isOpaque());
574fcaf7f86SDimitry Andric     Ty = PType->getNonOpaquePointerElementType();
575fcaf7f86SDimitry Andric   }
576*bdd1243dSDimitry Andric   auto SType = cast<StructType>(Ty);
577*bdd1243dSDimitry Andric   assert(isSpecialOpaqueType(SType) && "Not a special opaque builtin type");
578*bdd1243dSDimitry Andric   return SPIRV::lowerBuiltinType(SType, AccQual, MIRBuilder, this);
579fcaf7f86SDimitry Andric }
580fcaf7f86SDimitry Andric 
581*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(
582*bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,
583*bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, Register Reg) {
584fcaf7f86SDimitry Andric   if (!Reg.isValid())
585fcaf7f86SDimitry Andric     Reg = createTypeVReg(MIRBuilder);
586fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePointer)
587fcaf7f86SDimitry Andric       .addDef(Reg)
58881ad6265SDimitry Andric       .addImm(static_cast<uint32_t>(SC))
58981ad6265SDimitry Andric       .addUse(getSPIRVTypeID(ElemType));
590fcaf7f86SDimitry Andric }
591fcaf7f86SDimitry Andric 
592*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(
593*bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {
594fcaf7f86SDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)
595fcaf7f86SDimitry Andric       .addUse(createTypeVReg(MIRBuilder))
596fcaf7f86SDimitry Andric       .addImm(static_cast<uint32_t>(SC));
59781ad6265SDimitry Andric }
59881ad6265SDimitry Andric 
59981ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(
60081ad6265SDimitry Andric     SPIRVType *RetType, const SmallVectorImpl<SPIRVType *> &ArgTypes,
60181ad6265SDimitry Andric     MachineIRBuilder &MIRBuilder) {
60281ad6265SDimitry Andric   auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)
60381ad6265SDimitry Andric                  .addDef(createTypeVReg(MIRBuilder))
60481ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(RetType));
60581ad6265SDimitry Andric   for (const SPIRVType *ArgType : ArgTypes)
60681ad6265SDimitry Andric     MIB.addUse(getSPIRVTypeID(ArgType));
60781ad6265SDimitry Andric   return MIB;
60881ad6265SDimitry Andric }
60981ad6265SDimitry Andric 
610fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(
611fcaf7f86SDimitry Andric     const Type *Ty, SPIRVType *RetType,
612fcaf7f86SDimitry Andric     const SmallVectorImpl<SPIRVType *> &ArgTypes,
613fcaf7f86SDimitry Andric     MachineIRBuilder &MIRBuilder) {
614fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
615fcaf7f86SDimitry Andric   if (Reg.isValid())
616fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
617fcaf7f86SDimitry Andric   SPIRVType *SpirvType = getOpTypeFunction(RetType, ArgTypes, MIRBuilder);
618fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(Ty, SpirvType);
619fcaf7f86SDimitry Andric }
620fcaf7f86SDimitry Andric 
621*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::findSPIRVType(
622*bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
623*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
624fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
625fcaf7f86SDimitry Andric   if (Reg.isValid())
626fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
627fcaf7f86SDimitry Andric   if (ForwardPointerTypes.find(Ty) != ForwardPointerTypes.end())
628fcaf7f86SDimitry Andric     return ForwardPointerTypes[Ty];
629fcaf7f86SDimitry Andric   return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, EmitIR);
630fcaf7f86SDimitry Andric }
631fcaf7f86SDimitry Andric 
632fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getSPIRVTypeID(const SPIRVType *SpirvType) const {
633fcaf7f86SDimitry Andric   assert(SpirvType && "Attempting to get type id for nullptr type.");
634fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer)
635fcaf7f86SDimitry Andric     return SpirvType->uses().begin()->getReg();
636fcaf7f86SDimitry Andric   return SpirvType->defs().begin()->getReg();
637fcaf7f86SDimitry Andric }
638fcaf7f86SDimitry Andric 
639*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
640*bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
641*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccQual, bool EmitIR) {
642*bdd1243dSDimitry Andric   if (isSpecialOpaqueType(Ty))
643*bdd1243dSDimitry Andric     return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);
644fcaf7f86SDimitry Andric   auto &TypeToSPIRVTypeMap = DT.getTypes()->getAllUses();
645fcaf7f86SDimitry Andric   auto t = TypeToSPIRVTypeMap.find(Ty);
646fcaf7f86SDimitry Andric   if (t != TypeToSPIRVTypeMap.end()) {
647fcaf7f86SDimitry Andric     auto tt = t->second.find(&MIRBuilder.getMF());
648fcaf7f86SDimitry Andric     if (tt != t->second.end())
649fcaf7f86SDimitry Andric       return getSPIRVTypeForVReg(tt->second);
650fcaf7f86SDimitry Andric   }
651fcaf7f86SDimitry Andric 
65281ad6265SDimitry Andric   if (auto IType = dyn_cast<IntegerType>(Ty)) {
65381ad6265SDimitry Andric     const unsigned Width = IType->getBitWidth();
65481ad6265SDimitry Andric     return Width == 1 ? getOpTypeBool(MIRBuilder)
65581ad6265SDimitry Andric                       : getOpTypeInt(Width, MIRBuilder, false);
65681ad6265SDimitry Andric   }
65781ad6265SDimitry Andric   if (Ty->isFloatingPointTy())
65881ad6265SDimitry Andric     return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);
65981ad6265SDimitry Andric   if (Ty->isVoidTy())
66081ad6265SDimitry Andric     return getOpTypeVoid(MIRBuilder);
66181ad6265SDimitry Andric   if (Ty->isVectorTy()) {
662fcaf7f86SDimitry Andric     SPIRVType *El =
663fcaf7f86SDimitry Andric         findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder);
66481ad6265SDimitry Andric     return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,
66581ad6265SDimitry Andric                            MIRBuilder);
66681ad6265SDimitry Andric   }
66781ad6265SDimitry Andric   if (Ty->isArrayTy()) {
668fcaf7f86SDimitry Andric     SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder);
66981ad6265SDimitry Andric     return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder, EmitIR);
67081ad6265SDimitry Andric   }
671fcaf7f86SDimitry Andric   if (auto SType = dyn_cast<StructType>(Ty)) {
672fcaf7f86SDimitry Andric     if (SType->isOpaque())
673fcaf7f86SDimitry Andric       return getOpTypeOpaque(SType, MIRBuilder);
674fcaf7f86SDimitry Andric     return getOpTypeStruct(SType, MIRBuilder, EmitIR);
675fcaf7f86SDimitry Andric   }
67681ad6265SDimitry Andric   if (auto FType = dyn_cast<FunctionType>(Ty)) {
677fcaf7f86SDimitry Andric     SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder);
67881ad6265SDimitry Andric     SmallVector<SPIRVType *, 4> ParamTypes;
67981ad6265SDimitry Andric     for (const auto &t : FType->params()) {
680fcaf7f86SDimitry Andric       ParamTypes.push_back(findSPIRVType(t, MIRBuilder));
68181ad6265SDimitry Andric     }
68281ad6265SDimitry Andric     return getOpTypeFunction(RetTy, ParamTypes, MIRBuilder);
68381ad6265SDimitry Andric   }
68481ad6265SDimitry Andric   if (auto PType = dyn_cast<PointerType>(Ty)) {
68581ad6265SDimitry Andric     SPIRVType *SpvElementType;
68681ad6265SDimitry Andric     // At the moment, all opaque pointers correspond to i8 element type.
68781ad6265SDimitry Andric     // TODO: change the implementation once opaque pointers are supported
68881ad6265SDimitry Andric     // in the SPIR-V specification.
689fcaf7f86SDimitry Andric     if (PType->isOpaque())
69081ad6265SDimitry Andric       SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);
691fcaf7f86SDimitry Andric     else
692fcaf7f86SDimitry Andric       SpvElementType =
693fcaf7f86SDimitry Andric           findSPIRVType(PType->getNonOpaquePointerElementType(), MIRBuilder,
694fcaf7f86SDimitry Andric                         SPIRV::AccessQualifier::ReadWrite, EmitIR);
69581ad6265SDimitry Andric     auto SC = addressSpaceToStorageClass(PType->getAddressSpace());
696fcaf7f86SDimitry Andric     // Null pointer means we have a loop in type definitions, make and
697fcaf7f86SDimitry Andric     // return corresponding OpTypeForwardPointer.
698fcaf7f86SDimitry Andric     if (SpvElementType == nullptr) {
699fcaf7f86SDimitry Andric       if (ForwardPointerTypes.find(Ty) == ForwardPointerTypes.end())
700fcaf7f86SDimitry Andric         ForwardPointerTypes[PType] = getOpTypeForwardPointer(SC, MIRBuilder);
701fcaf7f86SDimitry Andric       return ForwardPointerTypes[PType];
702fcaf7f86SDimitry Andric     }
703fcaf7f86SDimitry Andric     Register Reg(0);
704fcaf7f86SDimitry Andric     // If we have forward pointer associated with this type, use its register
705fcaf7f86SDimitry Andric     // operand to create OpTypePointer.
706fcaf7f86SDimitry Andric     if (ForwardPointerTypes.find(PType) != ForwardPointerTypes.end())
707fcaf7f86SDimitry Andric       Reg = getSPIRVTypeID(ForwardPointerTypes[PType]);
708fcaf7f86SDimitry Andric 
709fcaf7f86SDimitry Andric     return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);
71081ad6265SDimitry Andric   }
71181ad6265SDimitry Andric   llvm_unreachable("Unable to convert LLVM type to SPIRVType");
71281ad6265SDimitry Andric }
71381ad6265SDimitry Andric 
714fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(
715fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
716*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
717fcaf7f86SDimitry Andric   if (TypesInProcessing.count(Ty) && !Ty->isPointerTy())
718fcaf7f86SDimitry Andric     return nullptr;
719fcaf7f86SDimitry Andric   TypesInProcessing.insert(Ty);
720fcaf7f86SDimitry Andric   SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
721fcaf7f86SDimitry Andric   TypesInProcessing.erase(Ty);
722fcaf7f86SDimitry Andric   VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;
723fcaf7f86SDimitry Andric   SPIRVToLLVMType[SpirvType] = Ty;
724fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
725fcaf7f86SDimitry Andric   // Do not add OpTypeForwardPointer to DT, a corresponding normal pointer type
726fcaf7f86SDimitry Andric   // will be added later. For special types it is already added to DT.
727fcaf7f86SDimitry Andric   if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() &&
728*bdd1243dSDimitry Andric       !isSpecialOpaqueType(Ty))
729fcaf7f86SDimitry Andric     DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType));
730fcaf7f86SDimitry Andric 
731fcaf7f86SDimitry Andric   return SpirvType;
732fcaf7f86SDimitry Andric }
733fcaf7f86SDimitry Andric 
73481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg) const {
73581ad6265SDimitry Andric   auto t = VRegToTypeMap.find(CurMF);
73681ad6265SDimitry Andric   if (t != VRegToTypeMap.end()) {
73781ad6265SDimitry Andric     auto tt = t->second.find(VReg);
73881ad6265SDimitry Andric     if (tt != t->second.end())
73981ad6265SDimitry Andric       return tt->second;
74081ad6265SDimitry Andric   }
74181ad6265SDimitry Andric   return nullptr;
74281ad6265SDimitry Andric }
74381ad6265SDimitry Andric 
74481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
745fcaf7f86SDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder,
746*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
747fcaf7f86SDimitry Andric   Register Reg = DT.find(Ty, &MIRBuilder.getMF());
748*bdd1243dSDimitry Andric   if (Reg.isValid() && !isSpecialOpaqueType(Ty))
749753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
750fcaf7f86SDimitry Andric   TypesInProcessing.clear();
751fcaf7f86SDimitry Andric   SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR);
752fcaf7f86SDimitry Andric   // Create normal pointer types for the corresponding OpTypeForwardPointers.
753fcaf7f86SDimitry Andric   for (auto &CU : ForwardPointerTypes) {
754fcaf7f86SDimitry Andric     const Type *Ty2 = CU.first;
755fcaf7f86SDimitry Andric     SPIRVType *STy2 = CU.second;
756fcaf7f86SDimitry Andric     if ((Reg = DT.find(Ty2, &MIRBuilder.getMF())).isValid())
757fcaf7f86SDimitry Andric       STy2 = getSPIRVTypeForVReg(Reg);
758fcaf7f86SDimitry Andric     else
759fcaf7f86SDimitry Andric       STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, EmitIR);
760fcaf7f86SDimitry Andric     if (Ty == Ty2)
761fcaf7f86SDimitry Andric       STy = STy2;
762fcaf7f86SDimitry Andric   }
763fcaf7f86SDimitry Andric   ForwardPointerTypes.clear();
764fcaf7f86SDimitry Andric   return STy;
76581ad6265SDimitry Andric }
76681ad6265SDimitry Andric 
76781ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOfType(Register VReg,
76881ad6265SDimitry Andric                                          unsigned TypeOpcode) const {
76981ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
77081ad6265SDimitry Andric   assert(Type && "isScalarOfType VReg has no type assigned");
77181ad6265SDimitry Andric   return Type->getOpcode() == TypeOpcode;
77281ad6265SDimitry Andric }
77381ad6265SDimitry Andric 
77481ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg,
77581ad6265SDimitry Andric                                                  unsigned TypeOpcode) const {
77681ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
77781ad6265SDimitry Andric   assert(Type && "isScalarOrVectorOfType VReg has no type assigned");
77881ad6265SDimitry Andric   if (Type->getOpcode() == TypeOpcode)
77981ad6265SDimitry Andric     return true;
78081ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
78181ad6265SDimitry Andric     Register ScalarTypeVReg = Type->getOperand(1).getReg();
78281ad6265SDimitry Andric     SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);
78381ad6265SDimitry Andric     return ScalarType->getOpcode() == TypeOpcode;
78481ad6265SDimitry Andric   }
78581ad6265SDimitry Andric   return false;
78681ad6265SDimitry Andric }
78781ad6265SDimitry Andric 
78881ad6265SDimitry Andric unsigned
78981ad6265SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorBitWidth(const SPIRVType *Type) const {
79081ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
79181ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
79281ad6265SDimitry Andric     auto EleTypeReg = Type->getOperand(1).getReg();
79381ad6265SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
79481ad6265SDimitry Andric   }
79581ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeInt ||
79681ad6265SDimitry Andric       Type->getOpcode() == SPIRV::OpTypeFloat)
79781ad6265SDimitry Andric     return Type->getOperand(1).getImm();
79881ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeBool)
79981ad6265SDimitry Andric     return 1;
80081ad6265SDimitry Andric   llvm_unreachable("Attempting to get bit width of non-integer/float type.");
80181ad6265SDimitry Andric }
80281ad6265SDimitry Andric 
80381ad6265SDimitry Andric bool SPIRVGlobalRegistry::isScalarOrVectorSigned(const SPIRVType *Type) const {
80481ad6265SDimitry Andric   assert(Type && "Invalid Type pointer");
80581ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeVector) {
80681ad6265SDimitry Andric     auto EleTypeReg = Type->getOperand(1).getReg();
80781ad6265SDimitry Andric     Type = getSPIRVTypeForVReg(EleTypeReg);
80881ad6265SDimitry Andric   }
80981ad6265SDimitry Andric   if (Type->getOpcode() == SPIRV::OpTypeInt)
81081ad6265SDimitry Andric     return Type->getOperand(2).getImm() != 0;
81181ad6265SDimitry Andric   llvm_unreachable("Attempting to get sign of non-integer type.");
81281ad6265SDimitry Andric }
81381ad6265SDimitry Andric 
814*bdd1243dSDimitry Andric SPIRV::StorageClass::StorageClass
81581ad6265SDimitry Andric SPIRVGlobalRegistry::getPointerStorageClass(Register VReg) const {
81681ad6265SDimitry Andric   SPIRVType *Type = getSPIRVTypeForVReg(VReg);
81781ad6265SDimitry Andric   assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&
81881ad6265SDimitry Andric          Type->getOperand(1).isImm() && "Pointer type is expected");
819*bdd1243dSDimitry Andric   return static_cast<SPIRV::StorageClass::StorageClass>(
820*bdd1243dSDimitry Andric       Type->getOperand(1).getImm());
821*bdd1243dSDimitry Andric }
822*bdd1243dSDimitry Andric 
823*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
824*bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
825*bdd1243dSDimitry Andric     uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,
826*bdd1243dSDimitry Andric     SPIRV::ImageFormat::ImageFormat ImageFormat,
827*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
828*bdd1243dSDimitry Andric   SPIRV::ImageTypeDescriptor TD(SPIRVToLLVMType.lookup(SampledType), Dim, Depth,
829*bdd1243dSDimitry Andric                                 Arrayed, Multisampled, Sampled, ImageFormat,
830*bdd1243dSDimitry Andric                                 AccessQual);
831*bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
832*bdd1243dSDimitry Andric     return Res;
833*bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
834*bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
835*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeImage)
836*bdd1243dSDimitry Andric       .addDef(ResVReg)
837*bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(SampledType))
838*bdd1243dSDimitry Andric       .addImm(Dim)
839*bdd1243dSDimitry Andric       .addImm(Depth)        // Depth (whether or not it is a Depth image).
840*bdd1243dSDimitry Andric       .addImm(Arrayed)      // Arrayed.
841*bdd1243dSDimitry Andric       .addImm(Multisampled) // Multisampled (0 = only single-sample).
842*bdd1243dSDimitry Andric       .addImm(Sampled)      // Sampled (0 = usage known at runtime).
843*bdd1243dSDimitry Andric       .addImm(ImageFormat)
844*bdd1243dSDimitry Andric       .addImm(AccessQual);
845*bdd1243dSDimitry Andric }
846*bdd1243dSDimitry Andric 
847*bdd1243dSDimitry Andric SPIRVType *
848*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {
849*bdd1243dSDimitry Andric   SPIRV::SamplerTypeDescriptor TD;
850*bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
851*bdd1243dSDimitry Andric     return Res;
852*bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
853*bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
854*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampler).addDef(ResVReg);
855*bdd1243dSDimitry Andric }
856*bdd1243dSDimitry Andric 
857*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(
858*bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder,
859*bdd1243dSDimitry Andric     SPIRV::AccessQualifier::AccessQualifier AccessQual) {
860*bdd1243dSDimitry Andric   SPIRV::PipeTypeDescriptor TD(AccessQual);
861*bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
862*bdd1243dSDimitry Andric     return Res;
863*bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
864*bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
865*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypePipe)
866*bdd1243dSDimitry Andric       .addDef(ResVReg)
867*bdd1243dSDimitry Andric       .addImm(AccessQual);
868*bdd1243dSDimitry Andric }
869*bdd1243dSDimitry Andric 
870*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(
871*bdd1243dSDimitry Andric     MachineIRBuilder &MIRBuilder) {
872*bdd1243dSDimitry Andric   SPIRV::DeviceEventTypeDescriptor TD;
873*bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
874*bdd1243dSDimitry Andric     return Res;
875*bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
876*bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
877*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent).addDef(ResVReg);
878*bdd1243dSDimitry Andric }
879*bdd1243dSDimitry Andric 
880*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(
881*bdd1243dSDimitry Andric     SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {
882*bdd1243dSDimitry Andric   SPIRV::SampledImageTypeDescriptor TD(
883*bdd1243dSDimitry Andric       SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(
884*bdd1243dSDimitry Andric           ImageType->getOperand(1).getReg())),
885*bdd1243dSDimitry Andric       ImageType);
886*bdd1243dSDimitry Andric   if (auto *Res = checkSpecialInstr(TD, MIRBuilder))
887*bdd1243dSDimitry Andric     return Res;
888*bdd1243dSDimitry Andric   Register ResVReg = createTypeVReg(MIRBuilder);
889*bdd1243dSDimitry Andric   DT.add(TD, &MIRBuilder.getMF(), ResVReg);
890*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)
891*bdd1243dSDimitry Andric       .addDef(ResVReg)
892*bdd1243dSDimitry Andric       .addUse(getSPIRVTypeID(ImageType));
893*bdd1243dSDimitry Andric }
894*bdd1243dSDimitry Andric 
895*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(
896*bdd1243dSDimitry Andric     const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {
897*bdd1243dSDimitry Andric   Register ResVReg = DT.find(Ty, &MIRBuilder.getMF());
898*bdd1243dSDimitry Andric   if (ResVReg.isValid())
899*bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(ResVReg);
900*bdd1243dSDimitry Andric   ResVReg = createTypeVReg(MIRBuilder);
901*bdd1243dSDimitry Andric   DT.add(Ty, &MIRBuilder.getMF(), ResVReg);
902*bdd1243dSDimitry Andric   return MIRBuilder.buildInstr(Opcode).addDef(ResVReg);
903*bdd1243dSDimitry Andric }
904*bdd1243dSDimitry Andric 
905*bdd1243dSDimitry Andric const MachineInstr *
906*bdd1243dSDimitry Andric SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
907*bdd1243dSDimitry Andric                                        MachineIRBuilder &MIRBuilder) {
908*bdd1243dSDimitry Andric   Register Reg = DT.find(TD, &MIRBuilder.getMF());
909*bdd1243dSDimitry Andric   if (Reg.isValid())
910*bdd1243dSDimitry Andric     return MIRBuilder.getMF().getRegInfo().getUniqueVRegDef(Reg);
911*bdd1243dSDimitry Andric   return nullptr;
912*bdd1243dSDimitry Andric }
913*bdd1243dSDimitry Andric 
914*bdd1243dSDimitry Andric // TODO: maybe use tablegen to implement this.
915*bdd1243dSDimitry Andric SPIRVType *
916*bdd1243dSDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(StringRef TypeStr,
917*bdd1243dSDimitry Andric                                                 MachineIRBuilder &MIRBuilder) {
918*bdd1243dSDimitry Andric   unsigned VecElts = 0;
919*bdd1243dSDimitry Andric   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
920*bdd1243dSDimitry Andric 
921*bdd1243dSDimitry Andric   // Parse type name in either "typeN" or "type vector[N]" format, where
922*bdd1243dSDimitry Andric   // N is the number of elements of the vector.
923*bdd1243dSDimitry Andric   Type *Type;
924*bdd1243dSDimitry Andric   if (TypeStr.startswith("void")) {
925*bdd1243dSDimitry Andric     Type = Type::getVoidTy(Ctx);
926*bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen("void"));
927*bdd1243dSDimitry Andric   } else if (TypeStr.startswith("int") || TypeStr.startswith("uint")) {
928*bdd1243dSDimitry Andric     Type = Type::getInt32Ty(Ctx);
929*bdd1243dSDimitry Andric     TypeStr = TypeStr.startswith("int") ? TypeStr.substr(strlen("int"))
930*bdd1243dSDimitry Andric                                         : TypeStr.substr(strlen("uint"));
931*bdd1243dSDimitry Andric   } else if (TypeStr.startswith("float")) {
932*bdd1243dSDimitry Andric     Type = Type::getFloatTy(Ctx);
933*bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen("float"));
934*bdd1243dSDimitry Andric   } else if (TypeStr.startswith("half")) {
935*bdd1243dSDimitry Andric     Type = Type::getHalfTy(Ctx);
936*bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen("half"));
937*bdd1243dSDimitry Andric   } else if (TypeStr.startswith("opencl.sampler_t")) {
938*bdd1243dSDimitry Andric     Type = StructType::create(Ctx, "opencl.sampler_t");
939*bdd1243dSDimitry Andric   } else
940*bdd1243dSDimitry Andric     llvm_unreachable("Unable to recognize SPIRV type name.");
941*bdd1243dSDimitry Andric   if (TypeStr.startswith(" vector[")) {
942*bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(strlen(" vector["));
943*bdd1243dSDimitry Andric     TypeStr = TypeStr.substr(0, TypeStr.find(']'));
944*bdd1243dSDimitry Andric   }
945*bdd1243dSDimitry Andric   TypeStr.getAsInteger(10, VecElts);
946*bdd1243dSDimitry Andric   auto SpirvTy = getOrCreateSPIRVType(Type, MIRBuilder);
947*bdd1243dSDimitry Andric   if (VecElts > 0)
948*bdd1243dSDimitry Andric     SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
949*bdd1243dSDimitry Andric   return SpirvTy;
95081ad6265SDimitry Andric }
95181ad6265SDimitry Andric 
95281ad6265SDimitry Andric SPIRVType *
95381ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(unsigned BitWidth,
95481ad6265SDimitry Andric                                                  MachineIRBuilder &MIRBuilder) {
95581ad6265SDimitry Andric   return getOrCreateSPIRVType(
95681ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), BitWidth),
95781ad6265SDimitry Andric       MIRBuilder);
95881ad6265SDimitry Andric }
95981ad6265SDimitry Andric 
960fcaf7f86SDimitry Andric SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,
961753f127fSDimitry Andric                                                         SPIRVType *SpirvType) {
962753f127fSDimitry Andric   assert(CurMF == SpirvType->getMF());
96381ad6265SDimitry Andric   VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;
96481ad6265SDimitry Andric   SPIRVToLLVMType[SpirvType] = LLVMTy;
965753f127fSDimitry Andric   DT.add(LLVMTy, CurMF, getSPIRVTypeID(SpirvType));
96681ad6265SDimitry Andric   return SpirvType;
96781ad6265SDimitry Andric }
96881ad6265SDimitry Andric 
96981ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(
97081ad6265SDimitry Andric     unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {
97181ad6265SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);
972753f127fSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
973753f127fSDimitry Andric   if (Reg.isValid())
974753f127fSDimitry Andric     return getSPIRVTypeForVReg(Reg);
97581ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
97681ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeInt))
97781ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
97881ad6265SDimitry Andric                  .addImm(BitWidth)
97981ad6265SDimitry Andric                  .addImm(0);
980fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
98181ad6265SDimitry Andric }
98281ad6265SDimitry Andric 
98381ad6265SDimitry Andric SPIRVType *
98481ad6265SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder) {
98581ad6265SDimitry Andric   return getOrCreateSPIRVType(
98681ad6265SDimitry Andric       IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),
98781ad6265SDimitry Andric       MIRBuilder);
98881ad6265SDimitry Andric }
98981ad6265SDimitry Andric 
990fcaf7f86SDimitry Andric SPIRVType *
991fcaf7f86SDimitry Andric SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
992fcaf7f86SDimitry Andric                                               const SPIRVInstrInfo &TII) {
993fcaf7f86SDimitry Andric   Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), 1);
994fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
995fcaf7f86SDimitry Andric   if (Reg.isValid())
996fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
997fcaf7f86SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
998fcaf7f86SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeBool))
999fcaf7f86SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()));
1000fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1001fcaf7f86SDimitry Andric }
1002fcaf7f86SDimitry Andric 
100381ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
100481ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder) {
100581ad6265SDimitry Andric   return getOrCreateSPIRVType(
100681ad6265SDimitry Andric       FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
100781ad6265SDimitry Andric                            NumElements),
100881ad6265SDimitry Andric       MIRBuilder);
100981ad6265SDimitry Andric }
101081ad6265SDimitry Andric 
101181ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
101281ad6265SDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
101381ad6265SDimitry Andric     const SPIRVInstrInfo &TII) {
101481ad6265SDimitry Andric   Type *LLVMTy = FixedVectorType::get(
101581ad6265SDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1016fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1017fcaf7f86SDimitry Andric   if (Reg.isValid())
1018fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
101981ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
102081ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeVector))
102181ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
102281ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
102381ad6265SDimitry Andric                  .addImm(NumElements);
1024fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
102581ad6265SDimitry Andric }
102681ad6265SDimitry Andric 
1027*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVArrayType(
1028*bdd1243dSDimitry Andric     SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
1029*bdd1243dSDimitry Andric     const SPIRVInstrInfo &TII) {
1030*bdd1243dSDimitry Andric   Type *LLVMTy = ArrayType::get(
1031*bdd1243dSDimitry Andric       const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
1032*bdd1243dSDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1033*bdd1243dSDimitry Andric   if (Reg.isValid())
1034*bdd1243dSDimitry Andric     return getSPIRVTypeForVReg(Reg);
1035*bdd1243dSDimitry Andric   MachineBasicBlock &BB = *I.getParent();
1036*bdd1243dSDimitry Andric   SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(32, I, TII);
1037*bdd1243dSDimitry Andric   Register Len = getOrCreateConstInt(NumElements, I, SpirvType, TII);
1038*bdd1243dSDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypeArray))
1039*bdd1243dSDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
1040*bdd1243dSDimitry Andric                  .addUse(getSPIRVTypeID(BaseType))
1041*bdd1243dSDimitry Andric                  .addUse(Len);
1042*bdd1243dSDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1043*bdd1243dSDimitry Andric }
1044*bdd1243dSDimitry Andric 
1045*bdd1243dSDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
1046*bdd1243dSDimitry Andric     SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
1047*bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SClass) {
104881ad6265SDimitry Andric   return getOrCreateSPIRVType(
104981ad6265SDimitry Andric       PointerType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
105081ad6265SDimitry Andric                        storageClassToAddressSpace(SClass)),
105181ad6265SDimitry Andric       MIRBuilder);
105281ad6265SDimitry Andric }
105381ad6265SDimitry Andric 
105481ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(
105581ad6265SDimitry Andric     SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &TII,
1056*bdd1243dSDimitry Andric     SPIRV::StorageClass::StorageClass SC) {
105781ad6265SDimitry Andric   Type *LLVMTy =
105881ad6265SDimitry Andric       PointerType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
105981ad6265SDimitry Andric                        storageClassToAddressSpace(SC));
1060fcaf7f86SDimitry Andric   Register Reg = DT.find(LLVMTy, CurMF);
1061fcaf7f86SDimitry Andric   if (Reg.isValid())
1062fcaf7f86SDimitry Andric     return getSPIRVTypeForVReg(Reg);
106381ad6265SDimitry Andric   MachineBasicBlock &BB = *I.getParent();
106481ad6265SDimitry Andric   auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpTypePointer))
106581ad6265SDimitry Andric                  .addDef(createTypeVReg(CurMF->getRegInfo()))
106681ad6265SDimitry Andric                  .addImm(static_cast<uint32_t>(SC))
106781ad6265SDimitry Andric                  .addUse(getSPIRVTypeID(BaseType));
1068fcaf7f86SDimitry Andric   return finishCreatingSPIRVType(LLVMTy, MIB);
1069fcaf7f86SDimitry Andric }
1070fcaf7f86SDimitry Andric 
1071fcaf7f86SDimitry Andric Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,
1072fcaf7f86SDimitry Andric                                                SPIRVType *SpvType,
1073fcaf7f86SDimitry Andric                                                const SPIRVInstrInfo &TII) {
1074fcaf7f86SDimitry Andric   assert(SpvType);
1075fcaf7f86SDimitry Andric   const Type *LLVMTy = getTypeForSPIRVType(SpvType);
1076fcaf7f86SDimitry Andric   assert(LLVMTy);
1077fcaf7f86SDimitry Andric   // Find a constant in DT or build a new one.
1078fcaf7f86SDimitry Andric   UndefValue *UV = UndefValue::get(const_cast<Type *>(LLVMTy));
1079fcaf7f86SDimitry Andric   Register Res = DT.find(UV, CurMF);
1080fcaf7f86SDimitry Andric   if (Res.isValid())
1081fcaf7f86SDimitry Andric     return Res;
1082fcaf7f86SDimitry Andric   LLT LLTy = LLT::scalar(32);
1083fcaf7f86SDimitry Andric   Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);
1084fcaf7f86SDimitry Andric   assignSPIRVTypeToVReg(SpvType, Res, *CurMF);
1085fcaf7f86SDimitry Andric   DT.add(UV, CurMF, Res);
1086fcaf7f86SDimitry Andric 
1087fcaf7f86SDimitry Andric   MachineInstrBuilder MIB;
1088fcaf7f86SDimitry Andric   MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
1089fcaf7f86SDimitry Andric             .addDef(Res)
1090fcaf7f86SDimitry Andric             .addUse(getSPIRVTypeID(SpvType));
1091fcaf7f86SDimitry Andric   const auto &ST = CurMF->getSubtarget();
1092fcaf7f86SDimitry Andric   constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),
1093fcaf7f86SDimitry Andric                                    *ST.getRegisterInfo(), *ST.getRegBankInfo());
1094fcaf7f86SDimitry Andric   return Res;
109581ad6265SDimitry Andric }
1096