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