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