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;
SPIRVGlobalRegistry(unsigned PointerSize)3081ad6265SDimitry Andric SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize)
31*0fca6ea1SDimitry Andric : PointerSize(PointerSize), Bound(0) {}
3281ad6265SDimitry Andric
assignIntTypeToVReg(unsigned BitWidth,Register VReg,MachineInstr & I,const SPIRVInstrInfo & TII)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 *
assignFloatTypeToVReg(unsigned BitWidth,Register VReg,MachineInstr & I,const SPIRVInstrInfo & TII)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
assignVectTypeToVReg(SPIRVType * BaseType,unsigned NumElements,Register VReg,MachineInstr & I,const SPIRVInstrInfo & TII)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
assignTypeToVReg(const Type * Type,Register VReg,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccessQual,bool EmitIR)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
assignSPIRVTypeToVReg(SPIRVType * SpirvType,Register VReg,MachineFunction & MF)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
createTypeVReg(MachineIRBuilder & MIRBuilder)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
createTypeVReg(MachineRegisterInfo & MRI)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
getOpTypeBool(MachineIRBuilder & MIRBuilder)8881ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {
8981ad6265SDimitry Andric return MIRBuilder.buildInstr(SPIRV::OpTypeBool)
9081ad6265SDimitry Andric .addDef(createTypeVReg(MIRBuilder));
9181ad6265SDimitry Andric }
9281ad6265SDimitry Andric
adjustOpTypeIntWidth(unsigned Width) const93*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
getOpTypeInt(unsigned Width,MachineIRBuilder & MIRBuilder,bool IsSigned)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
getOpTypeFloat(uint32_t Width,MachineIRBuilder & MIRBuilder)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
getOpTypeVoid(MachineIRBuilder & MIRBuilder)13981ad6265SDimitry Andric SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {
14081ad6265SDimitry Andric return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)
14181ad6265SDimitry Andric .addDef(createTypeVReg(MIRBuilder));
14281ad6265SDimitry Andric }
14381ad6265SDimitry Andric
getOpTypeVector(uint32_t NumElems,SPIRVType * ElemType,MachineIRBuilder & MIRBuilder)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>
getOrCreateConstIntReg(uint64_t Val,SPIRVType * SpvType,MachineIRBuilder * MIRBuilder,MachineInstr * I,const SPIRVInstrInfo * TII)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>
getOrCreateConstFloatReg(APFloat Val,SPIRVType * SpvType,MachineIRBuilder * MIRBuilder,MachineInstr * I,const SPIRVInstrInfo * TII)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
getOrCreateConstFP(APFloat Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,bool ZeroAsNull)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
getOrCreateConstInt(uint64_t Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,bool ZeroAsNull)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
buildConstantInt(uint64_t Val,MachineIRBuilder & MIRBuilder,SPIRVType * SpvType,bool EmitIR)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
buildConstantFP(APFloat Val,MachineIRBuilder & MIRBuilder,SPIRVType * SpvType)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
getOrCreateBaseRegister(Constant * Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,unsigned BitWidth)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
getOrCreateCompositeOrNull(Constant * Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,Constant * CA,unsigned BitWidth,unsigned ElemCnt,bool ZeroAsNull)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
getOrCreateConstVector(uint64_t Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,bool ZeroAsNull)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
getOrCreateConstVector(APFloat Val,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII,bool ZeroAsNull)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
getOrCreateConstIntArray(uint64_t Val,size_t Num,MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII)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
getOrCreateIntCompositeOrNull(uint64_t Val,MachineIRBuilder & MIRBuilder,SPIRVType * SpvType,bool EmitIR,Constant * CA,unsigned BitWidth,unsigned ElemCnt)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
getOrCreateConsIntVector(uint64_t Val,MachineIRBuilder & MIRBuilder,SPIRVType * SpvType,bool EmitIR)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
getOrCreateConstNullPtr(MachineIRBuilder & MIRBuilder,SPIRVType * SpvType)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
buildConstantSampler(Register ResReg,unsigned AddrMode,unsigned Param,unsigned FilerMode,MachineIRBuilder & MIRBuilder,SPIRVType * SpvType)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
buildGlobalVariable(Register ResVReg,SPIRVType * BaseType,StringRef Name,const GlobalValue * GV,SPIRV::StorageClass::StorageClass Storage,const MachineInstr * Init,bool IsConst,bool HasLinkageTy,SPIRV::LinkageType::LinkageType LinkageType,MachineIRBuilder & MIRBuilder,bool IsInstSelector)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
getOpTypeArray(uint32_t NumElems,SPIRVType * ElemType,MachineIRBuilder & MIRBuilder,bool EmitIR)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
getOpTypeOpaque(const StructType * Ty,MachineIRBuilder & MIRBuilder)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
getOpTypeStruct(const StructType * Ty,MachineIRBuilder & MIRBuilder,bool EmitIR)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
getOrCreateSpecialType(const Type * Ty,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccQual)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
getOpTypePointer(SPIRV::StorageClass::StorageClass SC,SPIRVType * ElemType,MachineIRBuilder & MIRBuilder,Register Reg)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
getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,MachineIRBuilder & MIRBuilder)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
getOpTypeFunction(SPIRVType * RetType,const SmallVectorImpl<SPIRVType * > & ArgTypes,MachineIRBuilder & MIRBuilder)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
getOrCreateOpTypeFunctionWithArgs(const Type * Ty,SPIRVType * RetType,const SmallVectorImpl<SPIRVType * > & ArgTypes,MachineIRBuilder & MIRBuilder)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
findSPIRVType(const Type * Ty,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccQual,bool EmitIR)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
getSPIRVTypeID(const SPIRVType * SpirvType) const811fcaf7f86SDimitry 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.
adjustIntTypeByWidth(const Type * Ty) const826*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
createSPIRVType(const Type * Ty,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccQual,bool EmitIR)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
restOfCreateSPIRVType(const Type * Ty,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccessQual,bool EmitIR)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 *
getSPIRVTypeForVReg(Register VReg,const MachineFunction * MF) const951*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
getOrCreateSPIRVType(const Type * Ty,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccessQual,bool EmitIR)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
isScalarOfType(Register VReg,unsigned TypeOpcode) const99781ad6265SDimitry 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
isScalarOrVectorOfType(Register VReg,unsigned TypeOpcode) const100481ad6265SDimitry 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
getScalarOrVectorComponentCount(Register VReg) const1019*0fca6ea1SDimitry Andric SPIRVGlobalRegistry::getScalarOrVectorComponentCount(Register VReg) const {
1020*0fca6ea1SDimitry Andric return getScalarOrVectorComponentCount(getSPIRVTypeForVReg(VReg));
1021*0fca6ea1SDimitry Andric }
1022*0fca6ea1SDimitry Andric
1023*0fca6ea1SDimitry Andric unsigned
getScalarOrVectorComponentCount(SPIRVType * Type) const1024*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
getScalarOrVectorBitWidth(const SPIRVType * Type) const103381ad6265SDimitry 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
getNumScalarOrVectorTotalBitWidth(const SPIRVType * Type) const1047*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
retrieveScalarOrVectorIntType(const SPIRVType * Type) const1061*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
isScalarOrVectorSigned(const SPIRVType * Type) const1068*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
getPointeeType(SPIRVType * PtrType)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
getPointeeTypeOp(Register PtrReg)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
isBitcastCompatible(const SPIRVType * Type1,const SPIRVType * Type2) const1084*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
getPointerStorageClass(Register VReg) const110481ad6265SDimitry 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
getOrCreateOpTypeImage(MachineIRBuilder & MIRBuilder,SPIRVType * SampledType,SPIRV::Dim::Dim Dim,uint32_t Depth,uint32_t Arrayed,uint32_t Multisampled,uint32_t Sampled,SPIRV::ImageFormat::ImageFormat ImageFormat,SPIRV::AccessQualifier::AccessQualifier AccessQual)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 *
getOrCreateOpTypeSampler(MachineIRBuilder & MIRBuilder)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
getOrCreateOpTypePipe(MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AccessQual)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
getOrCreateOpTypeDeviceEvent(MachineIRBuilder & MIRBuilder)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
getOrCreateOpTypeSampledImage(SPIRVType * ImageType,MachineIRBuilder & MIRBuilder)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
getOrCreateOpTypeCoopMatr(MachineIRBuilder & MIRBuilder,const TargetExtType * ExtensionType,const SPIRVType * ElemType,uint32_t Scope,uint32_t Rows,uint32_t Columns,uint32_t Use)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
getOrCreateOpTypeByOpcode(const Type * Ty,MachineIRBuilder & MIRBuilder,unsigned Opcode)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 *
checkSpecialInstr(const SPIRV::SpecialTypeDescriptor & TD,MachineIRBuilder & MIRBuilder)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
getOrCreateSPIRVTypeByName(StringRef TypeStr,MachineIRBuilder & MIRBuilder,SPIRV::StorageClass::StorageClass SC,SPIRV::AccessQualifier::AccessQualifier AQ)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 *
getOrCreateSPIRVIntegerType(unsigned BitWidth,MachineIRBuilder & MIRBuilder)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
finishCreatingSPIRVType(const Type * LLVMTy,SPIRVType * SpirvType)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
getOrCreateSPIRVType(unsigned BitWidth,MachineInstr & I,const SPIRVInstrInfo & TII,unsigned SPIRVOPcode,Type * LLVMTy)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
getOrCreateSPIRVIntegerType(unsigned BitWidth,MachineInstr & I,const SPIRVInstrInfo & TII)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
getOrCreateSPIRVFloatType(unsigned BitWidth,MachineInstr & I,const SPIRVInstrInfo & TII)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 *
getOrCreateSPIRVBoolType(MachineIRBuilder & MIRBuilder)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 *
getOrCreateSPIRVBoolType(MachineInstr & I,const SPIRVInstrInfo & TII)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
getOrCreateSPIRVVectorType(SPIRVType * BaseType,unsigned NumElements,MachineIRBuilder & MIRBuilder)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
getOrCreateSPIRVVectorType(SPIRVType * BaseType,unsigned NumElements,MachineInstr & I,const SPIRVInstrInfo & TII)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
getOrCreateSPIRVArrayType(SPIRVType * BaseType,unsigned NumElements,MachineInstr & I,const SPIRVInstrInfo & TII)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
getOrCreateSPIRVPointerType(SPIRVType * BaseType,MachineIRBuilder & MIRBuilder,SPIRV::StorageClass::StorageClass SC)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
getOrCreateSPIRVPointerType(SPIRVType * BaseType,MachineInstr & I,const SPIRVInstrInfo &,SPIRV::StorageClass::StorageClass SC)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
getOrCreateUndef(MachineInstr & I,SPIRVType * SpvType,const SPIRVInstrInfo & TII)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