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