brintos

brintos / llvm-project-archived public Read only

0
0
Text · 86.0 KiB · ae81d38 Raw
2176 lines · cpp
1//===-- SPIRVGlobalRegistry.cpp - SPIR-V Global Registry --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the implementation of the SPIRVGlobalRegistry class,10// which is used to maintain rich type information required for SPIR-V even11// after lowering from LLVM IR to GMIR. It can convert an llvm::Type into12// an OpTypeXXX instruction, and map it to a virtual register. Also it builds13// and supports consistency of constants and global variables.14//15//===----------------------------------------------------------------------===//16 17#include "SPIRVGlobalRegistry.h"18#include "SPIRV.h"19#include "SPIRVBuiltins.h"20#include "SPIRVSubtarget.h"21#include "SPIRVUtils.h"22#include "llvm/ADT/APInt.h"23#include "llvm/IR/Constants.h"24#include "llvm/IR/DiagnosticInfo.h"25#include "llvm/IR/Function.h"26#include "llvm/IR/IntrinsicInst.h"27#include "llvm/IR/Intrinsics.h"28#include "llvm/IR/IntrinsicsSPIRV.h"29#include "llvm/IR/Type.h"30#include "llvm/Support/Casting.h"31#include "llvm/Support/MathExtras.h"32#include <cassert>33#include <functional>34 35using namespace llvm;36 37static bool allowEmitFakeUse(const Value *Arg) {38  if (isSpvIntrinsic(Arg))39    return false;40  if (isa<AtomicCmpXchgInst, InsertValueInst, UndefValue>(Arg))41    return false;42  if (const auto *LI = dyn_cast<LoadInst>(Arg))43    if (LI->getType()->isAggregateType())44      return false;45  return true;46}47 48static unsigned typeToAddressSpace(const Type *Ty) {49  if (auto PType = dyn_cast<TypedPointerType>(Ty))50    return PType->getAddressSpace();51  if (auto PType = dyn_cast<PointerType>(Ty))52    return PType->getAddressSpace();53  if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);54      ExtTy && isTypedPointerWrapper(ExtTy))55    return ExtTy->getIntParameter(0);56  reportFatalInternalError("Unable to convert LLVM type to SPIRVType");57}58 59static bool60storageClassRequiresExplictLayout(SPIRV::StorageClass::StorageClass SC) {61  switch (SC) {62  case SPIRV::StorageClass::Uniform:63  case SPIRV::StorageClass::PushConstant:64  case SPIRV::StorageClass::StorageBuffer:65  case SPIRV::StorageClass::PhysicalStorageBufferEXT:66    return true;67  case SPIRV::StorageClass::UniformConstant:68  case SPIRV::StorageClass::Input:69  case SPIRV::StorageClass::Output:70  case SPIRV::StorageClass::Workgroup:71  case SPIRV::StorageClass::CrossWorkgroup:72  case SPIRV::StorageClass::Private:73  case SPIRV::StorageClass::Function:74  case SPIRV::StorageClass::Generic:75  case SPIRV::StorageClass::AtomicCounter:76  case SPIRV::StorageClass::Image:77  case SPIRV::StorageClass::CallableDataNV:78  case SPIRV::StorageClass::IncomingCallableDataNV:79  case SPIRV::StorageClass::RayPayloadNV:80  case SPIRV::StorageClass::HitAttributeNV:81  case SPIRV::StorageClass::IncomingRayPayloadNV:82  case SPIRV::StorageClass::ShaderRecordBufferNV:83  case SPIRV::StorageClass::CodeSectionINTEL:84  case SPIRV::StorageClass::DeviceOnlyINTEL:85  case SPIRV::StorageClass::HostOnlyINTEL:86    return false;87  }88  llvm_unreachable("Unknown SPIRV::StorageClass enum");89}90 91SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize)92    : PointerSize(PointerSize), Bound(0), CurMF(nullptr) {}93 94SPIRVType *SPIRVGlobalRegistry::assignIntTypeToVReg(unsigned BitWidth,95                                                    Register VReg,96                                                    MachineInstr &I,97                                                    const SPIRVInstrInfo &TII) {98  SPIRVType *SpirvType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);99  assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);100  return SpirvType;101}102 103SPIRVType *104SPIRVGlobalRegistry::assignFloatTypeToVReg(unsigned BitWidth, Register VReg,105                                           MachineInstr &I,106                                           const SPIRVInstrInfo &TII) {107  SPIRVType *SpirvType = getOrCreateSPIRVFloatType(BitWidth, I, TII);108  assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);109  return SpirvType;110}111 112SPIRVType *SPIRVGlobalRegistry::assignVectTypeToVReg(113    SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I,114    const SPIRVInstrInfo &TII) {115  SPIRVType *SpirvType =116      getOrCreateSPIRVVectorType(BaseType, NumElements, I, TII);117  assignSPIRVTypeToVReg(SpirvType, VReg, *CurMF);118  return SpirvType;119}120 121SPIRVType *SPIRVGlobalRegistry::assignTypeToVReg(122    const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder,123    SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {124  SPIRVType *SpirvType =125      getOrCreateSPIRVType(Type, MIRBuilder, AccessQual, EmitIR);126  assignSPIRVTypeToVReg(SpirvType, VReg, MIRBuilder.getMF());127  return SpirvType;128}129 130void SPIRVGlobalRegistry::assignSPIRVTypeToVReg(SPIRVType *SpirvType,131                                                Register VReg,132                                                const MachineFunction &MF) {133  VRegToTypeMap[&MF][VReg] = SpirvType;134}135 136static Register createTypeVReg(MachineRegisterInfo &MRI) {137  auto Res = MRI.createGenericVirtualRegister(LLT::scalar(64));138  MRI.setRegClass(Res, &SPIRV::TYPERegClass);139  return Res;140}141 142inline Register createTypeVReg(MachineIRBuilder &MIRBuilder) {143  return createTypeVReg(MIRBuilder.getMF().getRegInfo());144}145 146SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) {147  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {148    return MIRBuilder.buildInstr(SPIRV::OpTypeBool)149        .addDef(createTypeVReg(MIRBuilder));150  });151}152 153unsigned SPIRVGlobalRegistry::adjustOpTypeIntWidth(unsigned Width) const {154  if (Width > 64)155    report_fatal_error("Unsupported integer width!");156  const SPIRVSubtarget &ST = cast<SPIRVSubtarget>(CurMF->getSubtarget());157  if (ST.canUseExtension(158          SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers) ||159      ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4))160    return Width;161  if (Width <= 8)162    Width = 8;163  else if (Width <= 16)164    Width = 16;165  else if (Width <= 32)166    Width = 32;167  else168    Width = 64;169  return Width;170}171 172SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(unsigned Width,173                                             MachineIRBuilder &MIRBuilder,174                                             bool IsSigned) {175  Width = adjustOpTypeIntWidth(Width);176  const SPIRVSubtarget &ST =177      cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());178  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {179    if (Width == 4 && ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {180      MIRBuilder.buildInstr(SPIRV::OpExtension)181          .addImm(SPIRV::Extension::SPV_INTEL_int4);182      MIRBuilder.buildInstr(SPIRV::OpCapability)183          .addImm(SPIRV::Capability::Int4TypeINTEL);184    } else if ((!isPowerOf2_32(Width) || Width < 8) &&185               ST.canUseExtension(186                   SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers)) {187      MIRBuilder.buildInstr(SPIRV::OpExtension)188          .addImm(SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);189      MIRBuilder.buildInstr(SPIRV::OpCapability)190          .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);191    }192    return MIRBuilder.buildInstr(SPIRV::OpTypeInt)193        .addDef(createTypeVReg(MIRBuilder))194        .addImm(Width)195        .addImm(IsSigned ? 1 : 0);196  });197}198 199SPIRVType *SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,200                                               MachineIRBuilder &MIRBuilder) {201  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {202    return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)203        .addDef(createTypeVReg(MIRBuilder))204        .addImm(Width);205  });206}207 208SPIRVType *209SPIRVGlobalRegistry::getOpTypeFloat(uint32_t Width,210                                    MachineIRBuilder &MIRBuilder,211                                    SPIRV::FPEncoding::FPEncoding FPEncode) {212  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {213    return MIRBuilder.buildInstr(SPIRV::OpTypeFloat)214        .addDef(createTypeVReg(MIRBuilder))215        .addImm(Width)216        .addImm(FPEncode);217  });218}219 220SPIRVType *SPIRVGlobalRegistry::getOpTypeVoid(MachineIRBuilder &MIRBuilder) {221  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {222    return MIRBuilder.buildInstr(SPIRV::OpTypeVoid)223        .addDef(createTypeVReg(MIRBuilder));224  });225}226 227void SPIRVGlobalRegistry::invalidateMachineInstr(MachineInstr *MI) {228  // Other maps that may hold MachineInstr*:229  // - VRegToTypeMap: We cannot remove the definitions of `MI` from230  // VRegToTypeMap because some calls to invalidateMachineInstr are replacing MI231  // with another instruction defining the same register. We expect that if MI232  // is a type instruction, and it is still referenced in VRegToTypeMap, then233  // those registers are dead or the VRegToTypeMap is out-of-date. We do not234  // expect passes to ask for the SPIR-V type of a dead register. If the235  // VRegToTypeMap is out-of-date already, then there was an error before. We236  // cannot add an assert to verify this because the VRegToTypeMap can be237  // out-of-date.238  // - FunctionToInstr & FunctionToInstrRev: At this point, we should not be239  // deleting functions. No need to update.240  // - AliasInstMDMap: Would require a linear search, and the Intel Alias241  // instruction are not instructions instruction selection will be able to242  // remove.243 244  const SPIRVSubtarget &ST = MI->getMF()->getSubtarget<SPIRVSubtarget>();245  [[maybe_unused]] const SPIRVInstrInfo *TII = ST.getInstrInfo();246  assert(!TII->isAliasingInstr(*MI) &&247         "Cannot invalidate aliasing instructions.");248  assert(MI->getOpcode() != SPIRV::OpFunction &&249         "Cannot invalidate OpFunction.");250 251  if (MI->getOpcode() == SPIRV::OpFunctionCall) {252    if (const auto *F = dyn_cast<Function>(MI->getOperand(2).getGlobal())) {253      auto It = ForwardCalls.find(F);254      if (It != ForwardCalls.end()) {255        It->second.erase(MI);256        if (It->second.empty())257          ForwardCalls.erase(It);258      }259    }260  }261 262  const MachineFunction *MF = MI->getMF();263  auto It = LastInsertedTypeMap.find(MF);264  if (It != LastInsertedTypeMap.end() && It->second == MI)265    LastInsertedTypeMap.erase(MF);266  // remove from the duplicate tracker to avoid incorrect reuse267  erase(MI);268}269 270SPIRVType *SPIRVGlobalRegistry::createOpType(271    MachineIRBuilder &MIRBuilder,272    std::function<MachineInstr *(MachineIRBuilder &)> Op) {273  auto oldInsertPoint = MIRBuilder.getInsertPt();274  MachineBasicBlock *OldMBB = &MIRBuilder.getMBB();275  MachineBasicBlock *NewMBB = &*MIRBuilder.getMF().begin();276 277  auto LastInsertedType = LastInsertedTypeMap.find(CurMF);278  if (LastInsertedType != LastInsertedTypeMap.end()) {279    auto It = LastInsertedType->second->getIterator();280    // It might happen that this instruction was removed from the first MBB,281    // hence the Parent's check.282    MachineBasicBlock::iterator InsertAt;283    if (It->getParent() != NewMBB)284      InsertAt = oldInsertPoint->getParent() == NewMBB285                     ? oldInsertPoint286                     : getInsertPtValidEnd(NewMBB);287    else if (It->getNextNode())288      InsertAt = It->getNextNode()->getIterator();289    else290      InsertAt = getInsertPtValidEnd(NewMBB);291    MIRBuilder.setInsertPt(*NewMBB, InsertAt);292  } else {293    MIRBuilder.setInsertPt(*NewMBB, NewMBB->begin());294    auto Result = LastInsertedTypeMap.try_emplace(CurMF, nullptr);295    assert(Result.second);296    LastInsertedType = Result.first;297  }298 299  MachineInstr *Type = Op(MIRBuilder);300  // We expect all users of this function to insert definitions at the insertion301  // point set above that is always the first MBB.302  assert(Type->getParent() == NewMBB);303  LastInsertedType->second = Type;304 305  MIRBuilder.setInsertPt(*OldMBB, oldInsertPoint);306  return Type;307}308 309SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,310                                                SPIRVType *ElemType,311                                                MachineIRBuilder &MIRBuilder) {312  auto EleOpc = ElemType->getOpcode();313  (void)EleOpc;314  assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||315          EleOpc == SPIRV::OpTypeBool) &&316         "Invalid vector element type");317 318  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {319    return MIRBuilder.buildInstr(SPIRV::OpTypeVector)320        .addDef(createTypeVReg(MIRBuilder))321        .addUse(getSPIRVTypeID(ElemType))322        .addImm(NumElems);323  });324}325 326Register SPIRVGlobalRegistry::getOrCreateConstFP(APFloat Val, MachineInstr &I,327                                                 SPIRVType *SpvType,328                                                 const SPIRVInstrInfo &TII,329                                                 bool ZeroAsNull) {330  LLVMContext &Ctx = CurMF->getFunction().getContext();331  auto *const CF = ConstantFP::get(Ctx, Val);332  const MachineInstr *MI = findMI(CF, CurMF);333  if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||334             MI->getOpcode() == SPIRV::OpConstantF))335    return MI->getOperand(0).getReg();336  return createConstFP(CF, I, SpvType, TII, ZeroAsNull);337}338 339Register SPIRVGlobalRegistry::createConstFP(const ConstantFP *CF,340                                            MachineInstr &I, SPIRVType *SpvType,341                                            const SPIRVInstrInfo &TII,342                                            bool ZeroAsNull) {343  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);344  LLT LLTy = LLT::scalar(BitWidth);345  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);346  CurMF->getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);347  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);348 349  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);350  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());351  SPIRVType *NewType =352      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {353        MachineInstrBuilder MIB;354        // In OpenCL OpConstantNull - Scalar floating point: +0.0 (all bits 0)355        if (CF->getValue().isPosZero() && ZeroAsNull) {356          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)357                    .addDef(Res)358                    .addUse(getSPIRVTypeID(SpvType));359        } else {360          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)361                    .addDef(Res)362                    .addUse(getSPIRVTypeID(SpvType));363          addNumImm(APInt(BitWidth,364                          CF->getValueAPF().bitcastToAPInt().getZExtValue()),365                    MIB);366        }367        const auto &ST = CurMF->getSubtarget();368        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),369                                         *ST.getRegisterInfo(),370                                         *ST.getRegBankInfo());371        return MIB;372      });373  add(CF, NewType);374  return Res;375}376 377Register SPIRVGlobalRegistry::getOrCreateConstInt(uint64_t Val, MachineInstr &I,378                                                  SPIRVType *SpvType,379                                                  const SPIRVInstrInfo &TII,380                                                  bool ZeroAsNull) {381  const IntegerType *Ty = cast<IntegerType>(getTypeForSPIRVType(SpvType));382  auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);383  const MachineInstr *MI = findMI(CI, CurMF);384  if (MI && (MI->getOpcode() == SPIRV::OpConstantNull ||385             MI->getOpcode() == SPIRV::OpConstantI))386    return MI->getOperand(0).getReg();387  return createConstInt(CI, I, SpvType, TII, ZeroAsNull);388}389 390Register SPIRVGlobalRegistry::createConstInt(const ConstantInt *CI,391                                             MachineInstr &I,392                                             SPIRVType *SpvType,393                                             const SPIRVInstrInfo &TII,394                                             bool ZeroAsNull) {395  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);396  LLT LLTy = LLT::scalar(BitWidth);397  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);398  CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);399  assignIntTypeToVReg(BitWidth, Res, I, TII);400 401  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);402  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());403  SPIRVType *NewType =404      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {405        MachineInstrBuilder MIB;406        if (BitWidth == 1) {407          MIB = MIRBuilder408                    .buildInstr(CI->isZero() ? SPIRV::OpConstantFalse409                                             : SPIRV::OpConstantTrue)410                    .addDef(Res)411                    .addUse(getSPIRVTypeID(SpvType));412        } else if (!CI->isZero() || !ZeroAsNull) {413          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)414                    .addDef(Res)415                    .addUse(getSPIRVTypeID(SpvType));416          addNumImm(APInt(BitWidth, CI->getZExtValue()), MIB);417        } else {418          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)419                    .addDef(Res)420                    .addUse(getSPIRVTypeID(SpvType));421        }422        const auto &ST = CurMF->getSubtarget();423        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),424                                         *ST.getRegisterInfo(),425                                         *ST.getRegBankInfo());426        return MIB;427      });428  add(CI, NewType);429  return Res;430}431 432Register SPIRVGlobalRegistry::buildConstantInt(uint64_t Val,433                                               MachineIRBuilder &MIRBuilder,434                                               SPIRVType *SpvType, bool EmitIR,435                                               bool ZeroAsNull) {436  assert(SpvType);437  auto &MF = MIRBuilder.getMF();438  const IntegerType *Ty = cast<IntegerType>(getTypeForSPIRVType(SpvType));439  auto *const CI = ConstantInt::get(const_cast<IntegerType *>(Ty), Val);440  Register Res = find(CI, &MF);441  if (Res.isValid())442    return Res;443 444  unsigned BitWidth = getScalarOrVectorBitWidth(SpvType);445  LLT LLTy = LLT::scalar(BitWidth);446  MachineRegisterInfo &MRI = MF.getRegInfo();447  Res = MRI.createGenericVirtualRegister(LLTy);448  MRI.setRegClass(Res, &SPIRV::iIDRegClass);449  assignTypeToVReg(Ty, Res, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,450                   EmitIR);451 452  SPIRVType *NewType =453      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {454        if (EmitIR)455          return MIRBuilder.buildConstant(Res, *CI);456        Register SpvTypeReg = getSPIRVTypeID(SpvType);457        MachineInstrBuilder MIB;458        if (Val || !ZeroAsNull) {459          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantI)460                    .addDef(Res)461                    .addUse(SpvTypeReg);462          addNumImm(APInt(BitWidth, Val), MIB);463        } else {464          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)465                    .addDef(Res)466                    .addUse(SpvTypeReg);467        }468        const auto &Subtarget = CurMF->getSubtarget();469        constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),470                                         *Subtarget.getRegisterInfo(),471                                         *Subtarget.getRegBankInfo());472        return MIB;473      });474  add(CI, NewType);475  return Res;476}477 478Register SPIRVGlobalRegistry::buildConstantFP(APFloat Val,479                                              MachineIRBuilder &MIRBuilder,480                                              SPIRVType *SpvType) {481  auto &MF = MIRBuilder.getMF();482  LLVMContext &Ctx = MF.getFunction().getContext();483  if (!SpvType)484    SpvType = getOrCreateSPIRVType(Type::getFloatTy(Ctx), MIRBuilder,485                                   SPIRV::AccessQualifier::ReadWrite, true);486  auto *const CF = ConstantFP::get(Ctx, Val);487  Register Res = find(CF, &MF);488  if (Res.isValid())489    return Res;490 491  LLT LLTy = LLT::scalar(getScalarOrVectorBitWidth(SpvType));492  Res = MF.getRegInfo().createGenericVirtualRegister(LLTy);493  MF.getRegInfo().setRegClass(Res, &SPIRV::fIDRegClass);494  assignSPIRVTypeToVReg(SpvType, Res, MF);495 496  SPIRVType *NewType =497      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {498        MachineInstrBuilder MIB;499        MIB = MIRBuilder.buildInstr(SPIRV::OpConstantF)500                  .addDef(Res)501                  .addUse(getSPIRVTypeID(SpvType));502        addNumImm(CF->getValueAPF().bitcastToAPInt(), MIB);503        return MIB;504      });505  add(CF, NewType);506  return Res;507}508 509Register SPIRVGlobalRegistry::getOrCreateBaseRegister(510    Constant *Val, MachineInstr &I, SPIRVType *SpvType,511    const SPIRVInstrInfo &TII, unsigned BitWidth, bool ZeroAsNull) {512  SPIRVType *Type = SpvType;513  if (SpvType->getOpcode() == SPIRV::OpTypeVector ||514      SpvType->getOpcode() == SPIRV::OpTypeArray) {515    auto EleTypeReg = SpvType->getOperand(1).getReg();516    Type = getSPIRVTypeForVReg(EleTypeReg);517  }518  if (Type->getOpcode() == SPIRV::OpTypeFloat) {519    SPIRVType *SpvBaseType = getOrCreateSPIRVFloatType(BitWidth, I, TII);520    return getOrCreateConstFP(cast<ConstantFP>(Val)->getValue(), I, SpvBaseType,521                              TII, ZeroAsNull);522  }523  assert(Type->getOpcode() == SPIRV::OpTypeInt);524  SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, I, TII);525  return getOrCreateConstInt(Val->getUniqueInteger().getZExtValue(), I,526                             SpvBaseType, TII, ZeroAsNull);527}528 529Register SPIRVGlobalRegistry::getOrCreateCompositeOrNull(530    Constant *Val, MachineInstr &I, SPIRVType *SpvType,531    const SPIRVInstrInfo &TII, Constant *CA, unsigned BitWidth,532    unsigned ElemCnt, bool ZeroAsNull) {533  if (Register R = find(CA, CurMF); R.isValid())534    return R;535 536  bool IsNull = Val->isNullValue() && ZeroAsNull;537  Register ElemReg;538  if (!IsNull)539    ElemReg =540        getOrCreateBaseRegister(Val, I, SpvType, TII, BitWidth, ZeroAsNull);541 542  LLT LLTy = LLT::scalar(64);543  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);544  CurMF->getRegInfo().setRegClass(Res, getRegClass(SpvType));545  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);546 547  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);548  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());549  const MachineInstr *NewMI =550      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {551        MachineInstrBuilder MIB;552        if (!IsNull) {553          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)554                    .addDef(Res)555                    .addUse(getSPIRVTypeID(SpvType));556          for (unsigned i = 0; i < ElemCnt; ++i)557            MIB.addUse(ElemReg);558        } else {559          MIB = MIRBuilder.buildInstr(SPIRV::OpConstantNull)560                    .addDef(Res)561                    .addUse(getSPIRVTypeID(SpvType));562        }563        const auto &Subtarget = CurMF->getSubtarget();564        constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),565                                         *Subtarget.getRegisterInfo(),566                                         *Subtarget.getRegBankInfo());567        return MIB;568      });569  add(CA, NewMI);570  return Res;571}572 573Register SPIRVGlobalRegistry::getOrCreateConstVector(uint64_t Val,574                                                     MachineInstr &I,575                                                     SPIRVType *SpvType,576                                                     const SPIRVInstrInfo &TII,577                                                     bool ZeroAsNull) {578  const Type *LLVMTy = getTypeForSPIRVType(SpvType);579  assert(LLVMTy->isVectorTy());580  const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);581  Type *LLVMBaseTy = LLVMVecTy->getElementType();582  assert(LLVMBaseTy->isIntegerTy());583  auto *ConstVal = ConstantInt::get(LLVMBaseTy, Val);584  auto *ConstVec =585      ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);586  unsigned BW = getScalarOrVectorBitWidth(SpvType);587  return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,588                                    SpvType->getOperand(2).getImm(),589                                    ZeroAsNull);590}591 592Register SPIRVGlobalRegistry::getOrCreateConstVector(APFloat Val,593                                                     MachineInstr &I,594                                                     SPIRVType *SpvType,595                                                     const SPIRVInstrInfo &TII,596                                                     bool ZeroAsNull) {597  const Type *LLVMTy = getTypeForSPIRVType(SpvType);598  assert(LLVMTy->isVectorTy());599  const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);600  Type *LLVMBaseTy = LLVMVecTy->getElementType();601  assert(LLVMBaseTy->isFloatingPointTy());602  auto *ConstVal = ConstantFP::get(LLVMBaseTy, Val);603  auto *ConstVec =604      ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstVal);605  unsigned BW = getScalarOrVectorBitWidth(SpvType);606  return getOrCreateCompositeOrNull(ConstVal, I, SpvType, TII, ConstVec, BW,607                                    SpvType->getOperand(2).getImm(),608                                    ZeroAsNull);609}610 611Register SPIRVGlobalRegistry::getOrCreateConstIntArray(612    uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType,613    const SPIRVInstrInfo &TII) {614  const Type *LLVMTy = getTypeForSPIRVType(SpvType);615  assert(LLVMTy->isArrayTy());616  const ArrayType *LLVMArrTy = cast<ArrayType>(LLVMTy);617  Type *LLVMBaseTy = LLVMArrTy->getElementType();618  Constant *CI = ConstantInt::get(LLVMBaseTy, Val);619  SPIRVType *SpvBaseTy = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());620  unsigned BW = getScalarOrVectorBitWidth(SpvBaseTy);621  // The following is reasonably unique key that is better that [Val]. The naive622  // alternative would be something along the lines of:623  //   SmallVector<Constant *> NumCI(Num, CI);624  //   Constant *UniqueKey =625  //     ConstantArray::get(const_cast<ArrayType*>(LLVMArrTy), NumCI);626  // that would be a truly unique but dangerous key, because it could lead to627  // the creation of constants of arbitrary length (that is, the parameter of628  // memset) which were missing in the original module.629  Constant *UniqueKey = ConstantStruct::getAnon(630      {PoisonValue::get(const_cast<ArrayType *>(LLVMArrTy)),631       ConstantInt::get(LLVMBaseTy, Val), ConstantInt::get(LLVMBaseTy, Num)});632  return getOrCreateCompositeOrNull(CI, I, SpvType, TII, UniqueKey, BW,633                                    LLVMArrTy->getNumElements());634}635 636Register SPIRVGlobalRegistry::getOrCreateIntCompositeOrNull(637    uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR,638    Constant *CA, unsigned BitWidth, unsigned ElemCnt) {639  if (Register R = find(CA, CurMF); R.isValid())640    return R;641 642  Register ElemReg;643  if (Val || EmitIR) {644    SPIRVType *SpvBaseType = getOrCreateSPIRVIntegerType(BitWidth, MIRBuilder);645    ElemReg = buildConstantInt(Val, MIRBuilder, SpvBaseType, EmitIR);646  }647  LLT LLTy = EmitIR ? LLT::fixed_vector(ElemCnt, BitWidth) : LLT::scalar(64);648  Register Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);649  CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);650  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);651 652  const MachineInstr *NewMI =653      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {654        if (EmitIR)655          return MIRBuilder.buildSplatBuildVector(Res, ElemReg);656 657        if (Val) {658          auto MIB = MIRBuilder.buildInstr(SPIRV::OpConstantComposite)659                         .addDef(Res)660                         .addUse(getSPIRVTypeID(SpvType));661          for (unsigned i = 0; i < ElemCnt; ++i)662            MIB.addUse(ElemReg);663          return MIB;664        }665 666        return MIRBuilder.buildInstr(SPIRV::OpConstantNull)667            .addDef(Res)668            .addUse(getSPIRVTypeID(SpvType));669      });670  add(CA, NewMI);671  return Res;672}673 674Register675SPIRVGlobalRegistry::getOrCreateConsIntVector(uint64_t Val,676                                              MachineIRBuilder &MIRBuilder,677                                              SPIRVType *SpvType, bool EmitIR) {678  const Type *LLVMTy = getTypeForSPIRVType(SpvType);679  assert(LLVMTy->isVectorTy());680  const FixedVectorType *LLVMVecTy = cast<FixedVectorType>(LLVMTy);681  Type *LLVMBaseTy = LLVMVecTy->getElementType();682  const auto ConstInt = ConstantInt::get(LLVMBaseTy, Val);683  auto ConstVec =684      ConstantVector::getSplat(LLVMVecTy->getElementCount(), ConstInt);685  unsigned BW = getScalarOrVectorBitWidth(SpvType);686  return getOrCreateIntCompositeOrNull(Val, MIRBuilder, SpvType, EmitIR,687                                       ConstVec, BW,688                                       SpvType->getOperand(2).getImm());689}690 691Register692SPIRVGlobalRegistry::getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,693                                             SPIRVType *SpvType) {694  const Type *Ty = getTypeForSPIRVType(SpvType);695  unsigned AddressSpace = typeToAddressSpace(Ty);696  Type *ElemTy = ::getPointeeType(Ty);697  assert(ElemTy);698  const Constant *CP = ConstantTargetNone::get(699      dyn_cast<TargetExtType>(getTypedPointerWrapper(ElemTy, AddressSpace)));700  Register Res = find(CP, CurMF);701  if (Res.isValid())702    return Res;703 704  LLT LLTy = LLT::pointer(AddressSpace, PointerSize);705  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);706  CurMF->getRegInfo().setRegClass(Res, &SPIRV::pIDRegClass);707  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);708 709  const MachineInstr *NewMI =710      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {711        return MIRBuilder.buildInstr(SPIRV::OpConstantNull)712            .addDef(Res)713            .addUse(getSPIRVTypeID(SpvType));714      });715  add(CP, NewMI);716  return Res;717}718 719Register720SPIRVGlobalRegistry::buildConstantSampler(Register ResReg, unsigned AddrMode,721                                          unsigned Param, unsigned FilerMode,722                                          MachineIRBuilder &MIRBuilder) {723  auto Sampler =724      ResReg.isValid()725          ? ResReg726          : MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);727  SPIRVType *TypeSampler = getOrCreateOpTypeSampler(MIRBuilder);728  Register TypeSamplerReg = getSPIRVTypeID(TypeSampler);729  // We cannot use createOpType() logic here, because of the730  // GlobalISel/IRTranslator.cpp check for a tail call that expects that731  // MIRBuilder.getInsertPt() has a previous instruction. If this constant is732  // inserted as a result of "__translate_sampler_initializer()" this would733  // break this IRTranslator assumption.734  MIRBuilder.buildInstr(SPIRV::OpConstantSampler)735      .addDef(Sampler)736      .addUse(TypeSamplerReg)737      .addImm(AddrMode)738      .addImm(Param)739      .addImm(FilerMode);740  return Sampler;741}742 743Register SPIRVGlobalRegistry::buildGlobalVariable(744    Register ResVReg, SPIRVType *BaseType, StringRef Name,745    const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,746    const MachineInstr *Init, bool IsConst,747    const std::optional<SPIRV::LinkageType::LinkageType> &LinkageType,748    MachineIRBuilder &MIRBuilder, bool IsInstSelector) {749  const GlobalVariable *GVar = nullptr;750  if (GV) {751    GVar = cast<const GlobalVariable>(GV);752  } else {753    // If GV is not passed explicitly, use the name to find or construct754    // the global variable.755    Module *M = MIRBuilder.getMF().getFunction().getParent();756    GVar = M->getGlobalVariable(Name);757    if (GVar == nullptr) {758      const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type.759      // Module takes ownership of the global var.760      GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false,761                                GlobalValue::ExternalLinkage, nullptr,762                                Twine(Name));763    }764    GV = GVar;765  }766 767  const MachineFunction *MF = &MIRBuilder.getMF();768  Register Reg = find(GVar, MF);769  if (Reg.isValid()) {770    if (Reg != ResVReg)771      MIRBuilder.buildCopy(ResVReg, Reg);772    return ResVReg;773  }774 775  auto MIB = MIRBuilder.buildInstr(SPIRV::OpVariable)776                 .addDef(ResVReg)777                 .addUse(getSPIRVTypeID(BaseType))778                 .addImm(static_cast<uint32_t>(Storage));779  if (Init)780    MIB.addUse(Init->getOperand(0).getReg());781  // ISel may introduce a new register on this step, so we need to add it to782  // DT and correct its type avoiding fails on the next stage.783  if (IsInstSelector) {784    const auto &Subtarget = CurMF->getSubtarget();785    constrainSelectedInstRegOperands(*MIB, *Subtarget.getInstrInfo(),786                                     *Subtarget.getRegisterInfo(),787                                     *Subtarget.getRegBankInfo());788  }789  add(GVar, MIB);790 791  Reg = MIB->getOperand(0).getReg();792  addGlobalObject(GVar, MF, Reg);793 794  // Set to Reg the same type as ResVReg has.795  auto MRI = MIRBuilder.getMRI();796  if (Reg != ResVReg) {797    LLT RegLLTy =798        LLT::pointer(MRI->getType(ResVReg).getAddressSpace(), getPointerSize());799    MRI->setType(Reg, RegLLTy);800    assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());801  } else {802    // Our knowledge about the type may be updated.803    // If that's the case, we need to update a type804    // associated with the register.805    SPIRVType *DefType = getSPIRVTypeForVReg(ResVReg);806    if (!DefType || DefType != BaseType)807      assignSPIRVTypeToVReg(BaseType, Reg, MIRBuilder.getMF());808  }809 810  // If it's a global variable with name, output OpName for it.811  if (GVar && GVar->hasName())812    buildOpName(Reg, GVar->getName(), MIRBuilder);813 814  // Output decorations for the GV.815  // TODO: maybe move to GenerateDecorations pass.816  const SPIRVSubtarget &ST =817      cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());818  if (IsConst && !ST.isShader())819    buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {});820 821  if (GVar && GVar->getAlign().valueOrOne().value() != 1 && !ST.isShader()) {822    unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value();823    buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment});824  }825 826  if (LinkageType)827    buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,828                    {static_cast<uint32_t>(*LinkageType)}, Name);829 830  SPIRV::BuiltIn::BuiltIn BuiltInId;831  if (getSpirvBuiltInIdByName(Name, BuiltInId))832    buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::BuiltIn,833                    {static_cast<uint32_t>(BuiltInId)});834 835  // If it's a global variable with "spirv.Decorations" metadata node836  // recognize it as a SPIR-V friendly LLVM IR and parse "spirv.Decorations"837  // arguments.838  MDNode *GVarMD = nullptr;839  if (GVar && (GVarMD = GVar->getMetadata("spirv.Decorations")) != nullptr)840    buildOpSpirvDecorations(Reg, MIRBuilder, GVarMD, ST);841 842  return Reg;843}844 845// Returns a name based on the Type. Notes that this does not look at846// decorations, and will return the same string for two types that are the same847// except for decorations.848Register SPIRVGlobalRegistry::getOrCreateGlobalVariableWithBinding(849    const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name,850    MachineIRBuilder &MIRBuilder) {851  Register VarReg =852      MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);853 854  buildGlobalVariable(VarReg, VarType, Name, nullptr,855                      getPointerStorageClass(VarType), nullptr, false,856                      std::nullopt, MIRBuilder, false);857 858  buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::DescriptorSet, {Set});859  buildOpDecorate(VarReg, MIRBuilder, SPIRV::Decoration::Binding, {Binding});860  return VarReg;861}862 863// TODO: Double check the calls to getOpTypeArray to make sure that `ElemType`864// is explicitly laid out when required.865SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,866                                               SPIRVType *ElemType,867                                               MachineIRBuilder &MIRBuilder,868                                               bool ExplicitLayoutRequired,869                                               bool EmitIR) {870  assert((ElemType->getOpcode() != SPIRV::OpTypeVoid) &&871         "Invalid array element type");872  SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);873  SPIRVType *ArrayType = nullptr;874  const SPIRVSubtarget &ST =875      cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());876  if (NumElems != 0) {877    Register NumElementsVReg =878        buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);879    ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {880      return MIRBuilder.buildInstr(SPIRV::OpTypeArray)881          .addDef(createTypeVReg(MIRBuilder))882          .addUse(getSPIRVTypeID(ElemType))883          .addUse(NumElementsVReg);884    });885  } else {886    assert(ST.isShader() && "Runtime arrays are not allowed in non-shader "887                            "SPIR-V modules.");888    if (!ST.isShader())889      return nullptr;890    ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {891      return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)892          .addDef(createTypeVReg(MIRBuilder))893          .addUse(getSPIRVTypeID(ElemType));894    });895  }896 897  if (ExplicitLayoutRequired && !isResourceType(ElemType)) {898    Type *ET = const_cast<Type *>(getTypeForSPIRVType(ElemType));899    addArrayStrideDecorations(ArrayType->defs().begin()->getReg(), ET,900                              MIRBuilder);901  }902 903  return ArrayType;904}905 906SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,907                                                MachineIRBuilder &MIRBuilder) {908  assert(Ty->hasName());909  const StringRef Name = Ty->hasName() ? Ty->getName() : "";910  Register ResVReg = createTypeVReg(MIRBuilder);911  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {912    auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeOpaque).addDef(ResVReg);913    addStringImm(Name, MIB);914    buildOpName(ResVReg, Name, MIRBuilder);915    return MIB;916  });917}918 919SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(920    const StructType *Ty, MachineIRBuilder &MIRBuilder,921    SPIRV::AccessQualifier::AccessQualifier AccQual,922    StructOffsetDecorator Decorator, bool EmitIR) {923  Type *OriginalElementType = nullptr;924  uint64_t TotalSize = 0;925  if (matchPeeledArrayPattern(Ty, OriginalElementType, TotalSize)) {926    SPIRVType *ElementSPIRVType = findSPIRVType(927        OriginalElementType, MIRBuilder, AccQual,928        /* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);929    return getOpTypeArray(TotalSize, ElementSPIRVType, MIRBuilder,930                          /*ExplicitLayoutRequired=*/Decorator != nullptr,931                          EmitIR);932  }933 934  const SPIRVSubtarget &ST =935      cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());936  SmallVector<Register, 4> FieldTypes;937  constexpr unsigned MaxWordCount = UINT16_MAX;938  const size_t NumElements = Ty->getNumElements();939 940  size_t MaxNumElements = MaxWordCount - 2;941  size_t SPIRVStructNumElements = NumElements;942  if (NumElements > MaxNumElements) {943    // Do adjustments for continued instructions.944    SPIRVStructNumElements = MaxNumElements;945    MaxNumElements = MaxWordCount - 1;946  }947 948  for (const auto &Elem : Ty->elements()) {949    SPIRVType *ElemTy = findSPIRVType(950        toTypedPointer(Elem), MIRBuilder, AccQual,951        /* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);952    assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&953           "Invalid struct element type");954    FieldTypes.push_back(getSPIRVTypeID(ElemTy));955  }956  Register ResVReg = createTypeVReg(MIRBuilder);957  if (Ty->hasName())958    buildOpName(ResVReg, Ty->getName(), MIRBuilder);959  if (Ty->isPacked() && !ST.isShader())960    buildOpDecorate(ResVReg, MIRBuilder, SPIRV::Decoration::CPacked, {});961 962  SPIRVType *SPVType =963      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {964        auto MIBStruct =965            MIRBuilder.buildInstr(SPIRV::OpTypeStruct).addDef(ResVReg);966        for (size_t I = 0; I < SPIRVStructNumElements; ++I)967          MIBStruct.addUse(FieldTypes[I]);968        for (size_t I = SPIRVStructNumElements; I < NumElements;969             I += MaxNumElements) {970          auto MIBCont =971              MIRBuilder.buildInstr(SPIRV::OpTypeStructContinuedINTEL);972          for (size_t J = I; J < std::min(I + MaxNumElements, NumElements); ++J)973            MIBCont.addUse(FieldTypes[I]);974        }975        return MIBStruct;976      });977 978  if (Decorator)979    Decorator(SPVType->defs().begin()->getReg());980 981  return SPVType;982}983 984SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(985    const Type *Ty, MachineIRBuilder &MIRBuilder,986    SPIRV::AccessQualifier::AccessQualifier AccQual) {987  assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type");988  return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this);989}990 991SPIRVType *SPIRVGlobalRegistry::getOpTypePointer(992    SPIRV::StorageClass::StorageClass SC, SPIRVType *ElemType,993    MachineIRBuilder &MIRBuilder, Register Reg) {994  if (!Reg.isValid())995    Reg = createTypeVReg(MIRBuilder);996 997  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {998    return MIRBuilder.buildInstr(SPIRV::OpTypePointer)999        .addDef(Reg)1000        .addImm(static_cast<uint32_t>(SC))1001        .addUse(getSPIRVTypeID(ElemType));1002  });1003}1004 1005SPIRVType *SPIRVGlobalRegistry::getOpTypeForwardPointer(1006    SPIRV::StorageClass::StorageClass SC, MachineIRBuilder &MIRBuilder) {1007  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1008    return MIRBuilder.buildInstr(SPIRV::OpTypeForwardPointer)1009        .addUse(createTypeVReg(MIRBuilder))1010        .addImm(static_cast<uint32_t>(SC));1011  });1012}1013 1014SPIRVType *SPIRVGlobalRegistry::getOpTypeFunction(1015    const FunctionType *Ty, SPIRVType *RetType,1016    const SmallVectorImpl<SPIRVType *> &ArgTypes,1017    MachineIRBuilder &MIRBuilder) {1018  if (Ty->isVarArg()) {1019    Function &Fn = MIRBuilder.getMF().getFunction();1020    Ty->getContext().diagnose(DiagnosticInfoUnsupported(1021        Fn, "SPIR-V does not support variadic functions",1022        MIRBuilder.getDebugLoc()));1023  }1024  return createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1025    auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeFunction)1026                   .addDef(createTypeVReg(MIRBuilder))1027                   .addUse(getSPIRVTypeID(RetType));1028    for (const SPIRVType *ArgType : ArgTypes)1029      MIB.addUse(getSPIRVTypeID(ArgType));1030    return MIB;1031  });1032}1033 1034SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeFunctionWithArgs(1035    const Type *Ty, SPIRVType *RetType,1036    const SmallVectorImpl<SPIRVType *> &ArgTypes,1037    MachineIRBuilder &MIRBuilder) {1038  if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))1039    return MI;1040  const MachineInstr *NewMI =1041      getOpTypeFunction(cast<FunctionType>(Ty), RetType, ArgTypes, MIRBuilder);1042  add(Ty, false, NewMI);1043  return finishCreatingSPIRVType(Ty, NewMI);1044}1045 1046SPIRVType *SPIRVGlobalRegistry::findSPIRVType(1047    const Type *Ty, MachineIRBuilder &MIRBuilder,1048    SPIRV::AccessQualifier::AccessQualifier AccQual,1049    bool ExplicitLayoutRequired, bool EmitIR) {1050  Ty = adjustIntTypeByWidth(Ty);1051  // TODO: findMI needs to know if a layout is required.1052  if (const MachineInstr *MI =1053          findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))1054    return MI;1055  if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end())1056    return It->second;1057  return restOfCreateSPIRVType(Ty, MIRBuilder, AccQual, ExplicitLayoutRequired,1058                               EmitIR);1059}1060 1061Register SPIRVGlobalRegistry::getSPIRVTypeID(const SPIRVType *SpirvType) const {1062  assert(SpirvType && "Attempting to get type id for nullptr type.");1063  if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||1064      SpirvType->getOpcode() == SPIRV::OpTypeStructContinuedINTEL)1065    return SpirvType->uses().begin()->getReg();1066  return SpirvType->defs().begin()->getReg();1067}1068 1069// We need to use a new LLVM integer type if there is a mismatch between1070// number of bits in LLVM and SPIRV integer types to let DuplicateTracker1071// ensure uniqueness of a SPIRV type by the corresponding LLVM type. Without1072// such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create the1073// same "OpTypeInt 8" type for a series of LLVM integer types with number of1074// bits less than 8. This would lead to duplicate type definitions1075// eventually due to the method that DuplicateTracker utilizes to reason1076// about uniqueness of type records.1077const Type *SPIRVGlobalRegistry::adjustIntTypeByWidth(const Type *Ty) const {1078  if (auto IType = dyn_cast<IntegerType>(Ty)) {1079    unsigned SrcBitWidth = IType->getBitWidth();1080    if (SrcBitWidth > 1) {1081      unsigned BitWidth = adjustOpTypeIntWidth(SrcBitWidth);1082      // Maybe change source LLVM type to keep DuplicateTracker consistent.1083      if (SrcBitWidth != BitWidth)1084        Ty = IntegerType::get(Ty->getContext(), BitWidth);1085    }1086  }1087  return Ty;1088}1089 1090SPIRVType *SPIRVGlobalRegistry::createSPIRVType(1091    const Type *Ty, MachineIRBuilder &MIRBuilder,1092    SPIRV::AccessQualifier::AccessQualifier AccQual,1093    bool ExplicitLayoutRequired, bool EmitIR) {1094  if (isSpecialOpaqueType(Ty))1095    return getOrCreateSpecialType(Ty, MIRBuilder, AccQual);1096 1097  if (const MachineInstr *MI =1098          findMI(Ty, ExplicitLayoutRequired, &MIRBuilder.getMF()))1099    return MI;1100 1101  if (auto IType = dyn_cast<IntegerType>(Ty)) {1102    const unsigned Width = IType->getBitWidth();1103    return Width == 1 ? getOpTypeBool(MIRBuilder)1104                      : getOpTypeInt(Width, MIRBuilder, false);1105  }1106  if (Ty->isFloatingPointTy()) {1107    if (Ty->isBFloatTy()) {1108      return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder,1109                            SPIRV::FPEncoding::BFloat16KHR);1110    } else {1111      return getOpTypeFloat(Ty->getPrimitiveSizeInBits(), MIRBuilder);1112    }1113  }1114  if (Ty->isVoidTy())1115    return getOpTypeVoid(MIRBuilder);1116  if (Ty->isVectorTy()) {1117    SPIRVType *El =1118        findSPIRVType(cast<FixedVectorType>(Ty)->getElementType(), MIRBuilder,1119                      AccQual, ExplicitLayoutRequired, EmitIR);1120    return getOpTypeVector(cast<FixedVectorType>(Ty)->getNumElements(), El,1121                           MIRBuilder);1122  }1123  if (Ty->isArrayTy()) {1124    SPIRVType *El = findSPIRVType(Ty->getArrayElementType(), MIRBuilder,1125                                  AccQual, ExplicitLayoutRequired, EmitIR);1126    return getOpTypeArray(Ty->getArrayNumElements(), El, MIRBuilder,1127                          ExplicitLayoutRequired, EmitIR);1128  }1129  if (auto SType = dyn_cast<StructType>(Ty)) {1130    if (SType->isOpaque())1131      return getOpTypeOpaque(SType, MIRBuilder);1132 1133    StructOffsetDecorator Decorator = nullptr;1134    if (ExplicitLayoutRequired) {1135      Decorator = [&MIRBuilder, SType, this](Register Reg) {1136        addStructOffsetDecorations(Reg, const_cast<StructType *>(SType),1137                                   MIRBuilder);1138      };1139    }1140    return getOpTypeStruct(SType, MIRBuilder, AccQual, std::move(Decorator),1141                           EmitIR);1142  }1143  if (auto FType = dyn_cast<FunctionType>(Ty)) {1144    SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder,1145                                     AccQual, ExplicitLayoutRequired, EmitIR);1146    SmallVector<SPIRVType *, 4> ParamTypes;1147    for (const auto &ParamTy : FType->params())1148      ParamTypes.push_back(findSPIRVType(ParamTy, MIRBuilder, AccQual,1149                                         ExplicitLayoutRequired, EmitIR));1150    return getOpTypeFunction(FType, RetTy, ParamTypes, MIRBuilder);1151  }1152 1153  unsigned AddrSpace = typeToAddressSpace(Ty);1154  SPIRVType *SpvElementType = nullptr;1155  if (Type *ElemTy = ::getPointeeType(Ty))1156    SpvElementType = getOrCreateSPIRVType(ElemTy, MIRBuilder, AccQual, EmitIR);1157  else1158    SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder);1159 1160  // Get access to information about available extensions1161  const SPIRVSubtarget *ST =1162      static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());1163  auto SC = addressSpaceToStorageClass(AddrSpace, *ST);1164 1165  Type *ElemTy = ::getPointeeType(Ty);1166  if (!ElemTy) {1167    ElemTy = Type::getInt8Ty(MIRBuilder.getContext());1168  }1169 1170  // If we have forward pointer associated with this type, use its register1171  // operand to create OpTypePointer.1172  if (auto It = ForwardPointerTypes.find(Ty); It != ForwardPointerTypes.end()) {1173    Register Reg = getSPIRVTypeID(It->second);1174    // TODO: what does getOpTypePointer do?1175    return getOpTypePointer(SC, SpvElementType, MIRBuilder, Reg);1176  }1177 1178  return getOrCreateSPIRVPointerType(ElemTy, MIRBuilder, SC);1179}1180 1181SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType(1182    const Type *Ty, MachineIRBuilder &MIRBuilder,1183    SPIRV::AccessQualifier::AccessQualifier AccessQual,1184    bool ExplicitLayoutRequired, bool EmitIR) {1185  // TODO: Could this create a problem if one requires an explicit layout, and1186  // the next time it does not?1187  if (TypesInProcessing.count(Ty) && !isPointerTyOrWrapper(Ty))1188    return nullptr;1189  TypesInProcessing.insert(Ty);1190  SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual,1191                                         ExplicitLayoutRequired, EmitIR);1192  TypesInProcessing.erase(Ty);1193  VRegToTypeMap[&MIRBuilder.getMF()][getSPIRVTypeID(SpirvType)] = SpirvType;1194 1195  // TODO: We could end up with two SPIR-V types pointing to the same llvm type.1196  // Is that a problem?1197  SPIRVToLLVMType[SpirvType] = unifyPtrType(Ty);1198 1199  if (SpirvType->getOpcode() == SPIRV::OpTypeForwardPointer ||1200      findMI(Ty, false, &MIRBuilder.getMF()) || isSpecialOpaqueType(Ty))1201    return SpirvType;1202 1203  if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);1204      ExtTy && isTypedPointerWrapper(ExtTy))1205    add(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), SpirvType);1206  else if (!isPointerTy(Ty))1207    add(Ty, ExplicitLayoutRequired, SpirvType);1208  else if (isTypedPointerTy(Ty))1209    add(cast<TypedPointerType>(Ty)->getElementType(),1210        getPointerAddressSpace(Ty), SpirvType);1211  else1212    add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),1213        getPointerAddressSpace(Ty), SpirvType);1214  return SpirvType;1215}1216 1217SPIRVType *1218SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg,1219                                         const MachineFunction *MF) const {1220  auto t = VRegToTypeMap.find(MF ? MF : CurMF);1221  if (t != VRegToTypeMap.end()) {1222    auto tt = t->second.find(VReg);1223    if (tt != t->second.end())1224      return tt->second;1225  }1226  return nullptr;1227}1228 1229SPIRVType *SPIRVGlobalRegistry::getResultType(Register VReg,1230                                              MachineFunction *MF) {1231  if (!MF)1232    MF = CurMF;1233  MachineInstr *Instr = getVRegDef(MF->getRegInfo(), VReg);1234  return getSPIRVTypeForVReg(Instr->getOperand(1).getReg(), MF);1235}1236 1237SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(1238    const Type *Ty, MachineIRBuilder &MIRBuilder,1239    SPIRV::AccessQualifier::AccessQualifier AccessQual,1240    bool ExplicitLayoutRequired, bool EmitIR) {1241  const MachineFunction *MF = &MIRBuilder.getMF();1242  Register Reg;1243  if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);1244      ExtTy && isTypedPointerWrapper(ExtTy))1245    Reg = find(ExtTy->getTypeParameter(0), ExtTy->getIntParameter(0), MF);1246  else if (!isPointerTy(Ty))1247    Reg = find(Ty = adjustIntTypeByWidth(Ty), ExplicitLayoutRequired, MF);1248  else if (isTypedPointerTy(Ty))1249    Reg = find(cast<TypedPointerType>(Ty)->getElementType(),1250               getPointerAddressSpace(Ty), MF);1251  else1252    Reg = find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()),1253               getPointerAddressSpace(Ty), MF);1254  if (Reg.isValid() && !isSpecialOpaqueType(Ty))1255    return getSPIRVTypeForVReg(Reg);1256 1257  TypesInProcessing.clear();1258  SPIRVType *STy = restOfCreateSPIRVType(Ty, MIRBuilder, AccessQual,1259                                         ExplicitLayoutRequired, EmitIR);1260  // Create normal pointer types for the corresponding OpTypeForwardPointers.1261  for (auto &CU : ForwardPointerTypes) {1262    // Pointer type themselves do not require an explicit layout. The types1263    // they pointer to might, but that is taken care of when creating the type.1264    bool PtrNeedsLayout = false;1265    const Type *Ty2 = CU.first;1266    SPIRVType *STy2 = CU.second;1267    if ((Reg = find(Ty2, PtrNeedsLayout, MF)).isValid())1268      STy2 = getSPIRVTypeForVReg(Reg);1269    else1270      STy2 = restOfCreateSPIRVType(Ty2, MIRBuilder, AccessQual, PtrNeedsLayout,1271                                   EmitIR);1272    if (Ty == Ty2)1273      STy = STy2;1274  }1275  ForwardPointerTypes.clear();1276  return STy;1277}1278 1279bool SPIRVGlobalRegistry::isScalarOfType(Register VReg,1280                                         unsigned TypeOpcode) const {1281  SPIRVType *Type = getSPIRVTypeForVReg(VReg);1282  assert(Type && "isScalarOfType VReg has no type assigned");1283  return Type->getOpcode() == TypeOpcode;1284}1285 1286bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg,1287                                                 unsigned TypeOpcode) const {1288  SPIRVType *Type = getSPIRVTypeForVReg(VReg);1289  assert(Type && "isScalarOrVectorOfType VReg has no type assigned");1290  if (Type->getOpcode() == TypeOpcode)1291    return true;1292  if (Type->getOpcode() == SPIRV::OpTypeVector) {1293    Register ScalarTypeVReg = Type->getOperand(1).getReg();1294    SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarTypeVReg);1295    return ScalarType->getOpcode() == TypeOpcode;1296  }1297  return false;1298}1299 1300bool SPIRVGlobalRegistry::isResourceType(SPIRVType *Type) const {1301  switch (Type->getOpcode()) {1302  case SPIRV::OpTypeImage:1303  case SPIRV::OpTypeSampler:1304  case SPIRV::OpTypeSampledImage:1305    return true;1306  case SPIRV::OpTypeStruct:1307    return hasBlockDecoration(Type);1308  default:1309    return false;1310  }1311  return false;1312}1313unsigned1314SPIRVGlobalRegistry::getScalarOrVectorComponentCount(Register VReg) const {1315  return getScalarOrVectorComponentCount(getSPIRVTypeForVReg(VReg));1316}1317 1318unsigned1319SPIRVGlobalRegistry::getScalarOrVectorComponentCount(SPIRVType *Type) const {1320  if (!Type)1321    return 0;1322  return Type->getOpcode() == SPIRV::OpTypeVector1323             ? static_cast<unsigned>(Type->getOperand(2).getImm())1324             : 1;1325}1326 1327SPIRVType *1328SPIRVGlobalRegistry::getScalarOrVectorComponentType(Register VReg) const {1329  return getScalarOrVectorComponentType(getSPIRVTypeForVReg(VReg));1330}1331 1332SPIRVType *1333SPIRVGlobalRegistry::getScalarOrVectorComponentType(SPIRVType *Type) const {1334  if (!Type)1335    return nullptr;1336  Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector1337                           ? Type->getOperand(1).getReg()1338                           : Type->getOperand(0).getReg();1339  SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);1340  assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),1341                                ScalarType->getOpcode()));1342  return ScalarType;1343}1344 1345unsigned1346SPIRVGlobalRegistry::getScalarOrVectorBitWidth(const SPIRVType *Type) const {1347  assert(Type && "Invalid Type pointer");1348  if (Type->getOpcode() == SPIRV::OpTypeVector) {1349    auto EleTypeReg = Type->getOperand(1).getReg();1350    Type = getSPIRVTypeForVReg(EleTypeReg);1351  }1352  if (Type->getOpcode() == SPIRV::OpTypeInt ||1353      Type->getOpcode() == SPIRV::OpTypeFloat)1354    return Type->getOperand(1).getImm();1355  if (Type->getOpcode() == SPIRV::OpTypeBool)1356    return 1;1357  llvm_unreachable("Attempting to get bit width of non-integer/float type.");1358}1359 1360unsigned SPIRVGlobalRegistry::getNumScalarOrVectorTotalBitWidth(1361    const SPIRVType *Type) const {1362  assert(Type && "Invalid Type pointer");1363  unsigned NumElements = 1;1364  if (Type->getOpcode() == SPIRV::OpTypeVector) {1365    NumElements = static_cast<unsigned>(Type->getOperand(2).getImm());1366    Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());1367  }1368  return Type->getOpcode() == SPIRV::OpTypeInt ||1369                 Type->getOpcode() == SPIRV::OpTypeFloat1370             ? NumElements * Type->getOperand(1).getImm()1371             : 0;1372}1373 1374const SPIRVType *SPIRVGlobalRegistry::retrieveScalarOrVectorIntType(1375    const SPIRVType *Type) const {1376  if (Type && Type->getOpcode() == SPIRV::OpTypeVector)1377    Type = getSPIRVTypeForVReg(Type->getOperand(1).getReg());1378  return Type && Type->getOpcode() == SPIRV::OpTypeInt ? Type : nullptr;1379}1380 1381bool SPIRVGlobalRegistry::isScalarOrVectorSigned(const SPIRVType *Type) const {1382  const SPIRVType *IntType = retrieveScalarOrVectorIntType(Type);1383  return IntType && IntType->getOperand(2).getImm() != 0;1384}1385 1386SPIRVType *SPIRVGlobalRegistry::getPointeeType(SPIRVType *PtrType) {1387  return PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer1388             ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg())1389             : nullptr;1390}1391 1392unsigned SPIRVGlobalRegistry::getPointeeTypeOp(Register PtrReg) {1393  SPIRVType *ElemType = getPointeeType(getSPIRVTypeForVReg(PtrReg));1394  return ElemType ? ElemType->getOpcode() : 0;1395}1396 1397bool SPIRVGlobalRegistry::isBitcastCompatible(const SPIRVType *Type1,1398                                              const SPIRVType *Type2) const {1399  if (!Type1 || !Type2)1400    return false;1401  auto Op1 = Type1->getOpcode(), Op2 = Type2->getOpcode();1402  // Ignore difference between <1.5 and >=1.5 protocol versions:1403  // it's valid if either Result Type or Operand is a pointer, and the other1404  // is a pointer, an integer scalar, or an integer vector.1405  if (Op1 == SPIRV::OpTypePointer &&1406      (Op2 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type2)))1407    return true;1408  if (Op2 == SPIRV::OpTypePointer &&1409      (Op1 == SPIRV::OpTypePointer || retrieveScalarOrVectorIntType(Type1)))1410    return true;1411  unsigned Bits1 = getNumScalarOrVectorTotalBitWidth(Type1),1412           Bits2 = getNumScalarOrVectorTotalBitWidth(Type2);1413  return Bits1 > 0 && Bits1 == Bits2;1414}1415 1416SPIRV::StorageClass::StorageClass1417SPIRVGlobalRegistry::getPointerStorageClass(Register VReg) const {1418  SPIRVType *Type = getSPIRVTypeForVReg(VReg);1419  assert(Type && Type->getOpcode() == SPIRV::OpTypePointer &&1420         Type->getOperand(1).isImm() && "Pointer type is expected");1421  return getPointerStorageClass(Type);1422}1423 1424SPIRV::StorageClass::StorageClass1425SPIRVGlobalRegistry::getPointerStorageClass(const SPIRVType *Type) const {1426  return static_cast<SPIRV::StorageClass::StorageClass>(1427      Type->getOperand(1).getImm());1428}1429 1430SPIRVType *SPIRVGlobalRegistry::getOrCreateVulkanBufferType(1431    MachineIRBuilder &MIRBuilder, Type *ElemType,1432    SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr) {1433  auto Key = SPIRV::irhandle_vkbuffer(ElemType, SC, IsWritable);1434  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1435    return MI;1436 1437  bool ExplicitLayoutRequired = storageClassRequiresExplictLayout(SC);1438  // We need to get the SPIR-V type for the element here, so we can add the1439  // decoration to it.1440  auto *T = StructType::create(ElemType);1441  auto *BlockType =1442      getOrCreateSPIRVType(T, MIRBuilder, SPIRV::AccessQualifier::None,1443                           ExplicitLayoutRequired, EmitIr);1444 1445  buildOpDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,1446                  SPIRV::Decoration::Block, {});1447 1448  if (!IsWritable) {1449    buildOpMemberDecorate(BlockType->defs().begin()->getReg(), MIRBuilder,1450                          SPIRV::Decoration::NonWritable, 0, {});1451  }1452 1453  SPIRVType *R = getOrCreateSPIRVPointerTypeInternal(BlockType, MIRBuilder, SC);1454  add(Key, R);1455  return R;1456}1457 1458SPIRVType *1459SPIRVGlobalRegistry::getOrCreatePaddingType(MachineIRBuilder &MIRBuilder) {1460  auto Key = SPIRV::irhandle_padding();1461  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1462    return MI;1463  auto *T = Type::getInt8Ty(MIRBuilder.getContext());1464  SPIRVType *R = getOrCreateSPIRVIntegerType(8, MIRBuilder);1465  finishCreatingSPIRVType(T, R);1466  add(Key, R);1467  return R;1468}1469 1470SPIRVType *SPIRVGlobalRegistry::getOrCreateLayoutType(1471    MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr) {1472  auto Key = SPIRV::handle(T);1473  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1474    return MI;1475 1476  StructType *ST = cast<StructType>(T->getTypeParameter(0));1477  ArrayRef<uint32_t> Offsets = T->int_params().slice(1);1478  assert(ST->getNumElements() == Offsets.size());1479 1480  StructOffsetDecorator Decorator = [&MIRBuilder, &Offsets](Register Reg) {1481    for (uint32_t I = 0; I < Offsets.size(); ++I) {1482      buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,1483                            {Offsets[I]});1484    }1485  };1486 1487  // We need a new OpTypeStruct instruction because decorations will be1488  // different from a struct with an explicit layout created from a different1489  // entry point.1490  SPIRVType *SPIRVStructType =1491      getOpTypeStruct(ST, MIRBuilder, SPIRV::AccessQualifier::None,1492                      std::move(Decorator), EmitIr);1493  add(Key, SPIRVStructType);1494  return SPIRVStructType;1495}1496 1497SPIRVType *SPIRVGlobalRegistry::getImageType(1498    const TargetExtType *ExtensionType,1499    const SPIRV::AccessQualifier::AccessQualifier Qualifier,1500    MachineIRBuilder &MIRBuilder) {1501  assert(ExtensionType->getNumTypeParameters() == 1 &&1502         "SPIR-V image builtin type must have sampled type parameter!");1503  const SPIRVType *SampledType =1504      getOrCreateSPIRVType(ExtensionType->getTypeParameter(0), MIRBuilder,1505                           SPIRV::AccessQualifier::ReadWrite, true);1506  assert((ExtensionType->getNumIntParameters() == 7 ||1507          ExtensionType->getNumIntParameters() == 6) &&1508         "Invalid number of parameters for SPIR-V image builtin!");1509 1510  SPIRV::AccessQualifier::AccessQualifier accessQualifier =1511      SPIRV::AccessQualifier::None;1512  if (ExtensionType->getNumIntParameters() == 7) {1513    accessQualifier = Qualifier == SPIRV::AccessQualifier::WriteOnly1514                          ? SPIRV::AccessQualifier::WriteOnly1515                          : SPIRV::AccessQualifier::AccessQualifier(1516                                ExtensionType->getIntParameter(6));1517  }1518 1519  // Create or get an existing type from GlobalRegistry.1520  SPIRVType *R = getOrCreateOpTypeImage(1521      MIRBuilder, SampledType,1522      SPIRV::Dim::Dim(ExtensionType->getIntParameter(0)),1523      ExtensionType->getIntParameter(1), ExtensionType->getIntParameter(2),1524      ExtensionType->getIntParameter(3), ExtensionType->getIntParameter(4),1525      SPIRV::ImageFormat::ImageFormat(ExtensionType->getIntParameter(5)),1526      accessQualifier);1527  SPIRVToLLVMType[R] = ExtensionType;1528  return R;1529}1530 1531SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(1532    MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,1533    uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,1534    SPIRV::ImageFormat::ImageFormat ImageFormat,1535    SPIRV::AccessQualifier::AccessQualifier AccessQual) {1536  auto Key = SPIRV::irhandle_image(SPIRVToLLVMType.lookup(SampledType), Dim,1537                                   Depth, Arrayed, Multisampled, Sampled,1538                                   ImageFormat, AccessQual);1539  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1540    return MI;1541  const MachineInstr *NewMI =1542      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1543        auto MIB =1544            MIRBuilder.buildInstr(SPIRV::OpTypeImage)1545                .addDef(createTypeVReg(MIRBuilder))1546                .addUse(getSPIRVTypeID(SampledType))1547                .addImm(Dim)1548                .addImm(Depth)   // Depth (whether or not it is a Depth image).1549                .addImm(Arrayed) // Arrayed.1550                .addImm(Multisampled) // Multisampled (0 = only single-sample).1551                .addImm(Sampled)      // Sampled (0 = usage known at runtime).1552                .addImm(ImageFormat);1553        if (AccessQual != SPIRV::AccessQualifier::None)1554          MIB.addImm(AccessQual);1555        return MIB;1556      });1557  add(Key, NewMI);1558  return NewMI;1559}1560 1561SPIRVType *1562SPIRVGlobalRegistry::getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder) {1563  auto Key = SPIRV::irhandle_sampler();1564  const MachineFunction *MF = &MIRBuilder.getMF();1565  if (const MachineInstr *MI = findMI(Key, MF))1566    return MI;1567  const MachineInstr *NewMI =1568      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1569        return MIRBuilder.buildInstr(SPIRV::OpTypeSampler)1570            .addDef(createTypeVReg(MIRBuilder));1571      });1572  add(Key, NewMI);1573  return NewMI;1574}1575 1576SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypePipe(1577    MachineIRBuilder &MIRBuilder,1578    SPIRV::AccessQualifier::AccessQualifier AccessQual) {1579  auto Key = SPIRV::irhandle_pipe(AccessQual);1580  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1581    return MI;1582  const MachineInstr *NewMI =1583      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1584        return MIRBuilder.buildInstr(SPIRV::OpTypePipe)1585            .addDef(createTypeVReg(MIRBuilder))1586            .addImm(AccessQual);1587      });1588  add(Key, NewMI);1589  return NewMI;1590}1591 1592SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeDeviceEvent(1593    MachineIRBuilder &MIRBuilder) {1594  auto Key = SPIRV::irhandle_event();1595  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1596    return MI;1597  const MachineInstr *NewMI =1598      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1599        return MIRBuilder.buildInstr(SPIRV::OpTypeDeviceEvent)1600            .addDef(createTypeVReg(MIRBuilder));1601      });1602  add(Key, NewMI);1603  return NewMI;1604}1605 1606SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeSampledImage(1607    SPIRVType *ImageType, MachineIRBuilder &MIRBuilder) {1608  auto Key = SPIRV::irhandle_sampled_image(1609      SPIRVToLLVMType.lookup(MIRBuilder.getMF().getRegInfo().getVRegDef(1610          ImageType->getOperand(1).getReg())),1611      ImageType);1612  if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))1613    return MI;1614  const MachineInstr *NewMI =1615      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1616        return MIRBuilder.buildInstr(SPIRV::OpTypeSampledImage)1617            .addDef(createTypeVReg(MIRBuilder))1618            .addUse(getSPIRVTypeID(ImageType));1619      });1620  add(Key, NewMI);1621  return NewMI;1622}1623 1624SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeCoopMatr(1625    MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType,1626    const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns,1627    uint32_t Use, bool EmitIR) {1628  if (const MachineInstr *MI =1629          findMI(ExtensionType, false, &MIRBuilder.getMF()))1630    return MI;1631  const MachineInstr *NewMI =1632      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1633        SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);1634        const Type *ET = getTypeForSPIRVType(ElemType);1635        if (ET->isIntegerTy() && ET->getIntegerBitWidth() == 4 &&1636            cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget())1637                .canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {1638          MIRBuilder.buildInstr(SPIRV::OpCapability)1639              .addImm(SPIRV::Capability::Int4CooperativeMatrixINTEL);1640        }1641        return MIRBuilder.buildInstr(SPIRV::OpTypeCooperativeMatrixKHR)1642            .addDef(createTypeVReg(MIRBuilder))1643            .addUse(getSPIRVTypeID(ElemType))1644            .addUse(buildConstantInt(Scope, MIRBuilder, SpvTypeInt32, EmitIR))1645            .addUse(buildConstantInt(Rows, MIRBuilder, SpvTypeInt32, EmitIR))1646            .addUse(buildConstantInt(Columns, MIRBuilder, SpvTypeInt32, EmitIR))1647            .addUse(buildConstantInt(Use, MIRBuilder, SpvTypeInt32, EmitIR));1648      });1649  add(ExtensionType, false, NewMI);1650  return NewMI;1651}1652 1653SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeByOpcode(1654    const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode) {1655  if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))1656    return MI;1657  const MachineInstr *NewMI =1658      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1659        return MIRBuilder.buildInstr(Opcode).addDef(createTypeVReg(MIRBuilder));1660      });1661  add(Ty, false, NewMI);1662  return NewMI;1663}1664 1665SPIRVType *SPIRVGlobalRegistry::getOrCreateUnknownType(1666    const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode,1667    const ArrayRef<MCOperand> Operands) {1668  if (const MachineInstr *MI = findMI(Ty, false, &MIRBuilder.getMF()))1669    return MI;1670  Register ResVReg = createTypeVReg(MIRBuilder);1671  const MachineInstr *NewMI =1672      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1673        MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::UNKNOWN_type)1674                                      .addDef(ResVReg)1675                                      .addImm(Opcode);1676        for (MCOperand Operand : Operands) {1677          if (Operand.isReg()) {1678            MIB.addUse(Operand.getReg());1679          } else if (Operand.isImm()) {1680            MIB.addImm(Operand.getImm());1681          }1682        }1683        return MIB;1684      });1685  add(Ty, false, NewMI);1686  return NewMI;1687}1688 1689// Returns nullptr if unable to recognize SPIRV type name1690SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(1691    StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR,1692    SPIRV::StorageClass::StorageClass SC,1693    SPIRV::AccessQualifier::AccessQualifier AQ) {1694  unsigned VecElts = 0;1695  auto &Ctx = MIRBuilder.getMF().getFunction().getContext();1696 1697  // Parse strings representing either a SPIR-V or OpenCL builtin type.1698  if (hasBuiltinTypePrefix(TypeStr))1699    return getOrCreateSPIRVType(SPIRV::parseBuiltinTypeNameToTargetExtType(1700                                    TypeStr.str(), MIRBuilder.getContext()),1701                                MIRBuilder, AQ, false, true);1702 1703  // Parse type name in either "typeN" or "type vector[N]" format, where1704  // N is the number of elements of the vector.1705  Type *Ty;1706 1707  Ty = parseBasicTypeName(TypeStr, Ctx);1708  if (!Ty)1709    // Unable to recognize SPIRV type name1710    return nullptr;1711 1712  const SPIRVType *SpirvTy =1713      getOrCreateSPIRVType(Ty, MIRBuilder, AQ, false, true);1714 1715  // Handle "type*" or  "type* vector[N]".1716  if (TypeStr.consume_front("*"))1717    SpirvTy = getOrCreateSPIRVPointerType(Ty, MIRBuilder, SC);1718 1719  // Handle "typeN*" or  "type vector[N]*".1720  bool IsPtrToVec = TypeStr.consume_back("*");1721 1722  if (TypeStr.consume_front(" vector[")) {1723    TypeStr = TypeStr.substr(0, TypeStr.find(']'));1724  }1725  TypeStr.getAsInteger(10, VecElts);1726  if (VecElts > 0)1727    SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder, EmitIR);1728 1729  if (IsPtrToVec)1730    SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);1731 1732  return SpirvTy;1733}1734 1735SPIRVType *1736SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(unsigned BitWidth,1737                                                 MachineIRBuilder &MIRBuilder) {1738  return getOrCreateSPIRVType(1739      IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), BitWidth),1740      MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, true);1741}1742 1743SPIRVType *SPIRVGlobalRegistry::finishCreatingSPIRVType(const Type *LLVMTy,1744                                                        SPIRVType *SpirvType) {1745  assert(CurMF == SpirvType->getMF());1746  VRegToTypeMap[CurMF][getSPIRVTypeID(SpirvType)] = SpirvType;1747  SPIRVToLLVMType[SpirvType] = unifyPtrType(LLVMTy);1748  return SpirvType;1749}1750 1751SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(unsigned BitWidth,1752                                                     MachineInstr &I,1753                                                     const SPIRVInstrInfo &TII,1754                                                     unsigned SPIRVOPcode,1755                                                     Type *Ty) {1756  if (const MachineInstr *MI = findMI(Ty, false, CurMF))1757    return MI;1758  MachineBasicBlock &DepMBB = I.getMF()->front();1759  MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());1760  const MachineInstr *NewMI =1761      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1762        auto NewTypeMI = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),1763                                 MIRBuilder.getDL(), TII.get(SPIRVOPcode))1764                             .addDef(createTypeVReg(CurMF->getRegInfo()))1765                             .addImm(BitWidth);1766        // Don't add Encoding to FP type1767        if (!Ty->isFloatTy()) {1768          return NewTypeMI.addImm(0);1769        } else {1770          return NewTypeMI;1771        }1772      });1773  add(Ty, false, NewMI);1774  return finishCreatingSPIRVType(Ty, NewMI);1775}1776 1777SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVIntegerType(1778    unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {1779  // Maybe adjust bit width to keep DuplicateTracker consistent. Without1780  // such an adjustment SPIRVGlobalRegistry::getOpTypeInt() could create, for1781  // example, the same "OpTypeInt 8" type for a series of LLVM integer types1782  // with number of bits less than 8, causing duplicate type definitions.1783  if (BitWidth > 1)1784    BitWidth = adjustOpTypeIntWidth(BitWidth);1785  Type *LLVMTy = IntegerType::get(CurMF->getFunction().getContext(), BitWidth);1786  return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeInt, LLVMTy);1787}1788 1789SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVFloatType(1790    unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII) {1791  LLVMContext &Ctx = CurMF->getFunction().getContext();1792  Type *LLVMTy;1793  switch (BitWidth) {1794  case 16:1795    LLVMTy = Type::getHalfTy(Ctx);1796    break;1797  case 32:1798    LLVMTy = Type::getFloatTy(Ctx);1799    break;1800  case 64:1801    LLVMTy = Type::getDoubleTy(Ctx);1802    break;1803  default:1804    llvm_unreachable("Bit width is of unexpected size.");1805  }1806  return getOrCreateSPIRVType(BitWidth, I, TII, SPIRV::OpTypeFloat, LLVMTy);1807}1808 1809SPIRVType *1810SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder,1811                                              bool EmitIR) {1812  return getOrCreateSPIRVType(1813      IntegerType::get(MIRBuilder.getMF().getFunction().getContext(), 1),1814      MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);1815}1816 1817SPIRVType *1818SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,1819                                              const SPIRVInstrInfo &TII) {1820  Type *Ty = IntegerType::get(CurMF->getFunction().getContext(), 1);1821  if (const MachineInstr *MI = findMI(Ty, false, CurMF))1822    return MI;1823  MachineBasicBlock &DepMBB = I.getMF()->front();1824  MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());1825  const MachineInstr *NewMI =1826      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1827        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),1828                       MIRBuilder.getDL(), TII.get(SPIRV::OpTypeBool))1829            .addDef(createTypeVReg(CurMF->getRegInfo()));1830      });1831  add(Ty, false, NewMI);1832  return finishCreatingSPIRVType(Ty, NewMI);1833}1834 1835SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(1836    SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder,1837    bool EmitIR) {1838  return getOrCreateSPIRVType(1839      FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),1840                           NumElements),1841      MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false, EmitIR);1842}1843 1844SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(1845    SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,1846    const SPIRVInstrInfo &TII) {1847  Type *Ty = FixedVectorType::get(1848      const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);1849  if (const MachineInstr *MI = findMI(Ty, false, CurMF))1850    return MI;1851  MachineInstr *DepMI = const_cast<MachineInstr *>(BaseType);1852  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());1853  const MachineInstr *NewMI =1854      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1855        return BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),1856                       MIRBuilder.getDL(), TII.get(SPIRV::OpTypeVector))1857            .addDef(createTypeVReg(CurMF->getRegInfo()))1858            .addUse(getSPIRVTypeID(BaseType))1859            .addImm(NumElements);1860      });1861  add(Ty, false, NewMI);1862  return finishCreatingSPIRVType(Ty, NewMI);1863}1864 1865SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(1866    const Type *BaseType, MachineInstr &I,1867    SPIRV::StorageClass::StorageClass SC) {1868  MachineIRBuilder MIRBuilder(I);1869  return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC);1870}1871 1872SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(1873    const Type *BaseType, MachineIRBuilder &MIRBuilder,1874    SPIRV::StorageClass::StorageClass SC) {1875  // TODO: Need to check if EmitIr should always be true.1876  SPIRVType *SpirvBaseType = getOrCreateSPIRVType(1877      BaseType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,1878      storageClassRequiresExplictLayout(SC), true);1879  assert(SpirvBaseType);1880  return getOrCreateSPIRVPointerTypeInternal(SpirvBaseType, MIRBuilder, SC);1881}1882 1883SPIRVType *SPIRVGlobalRegistry::changePointerStorageClass(1884    SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I) {1885  [[maybe_unused]] SPIRV::StorageClass::StorageClass OldSC =1886      getPointerStorageClass(PtrType);1887  assert(storageClassRequiresExplictLayout(OldSC) ==1888         storageClassRequiresExplictLayout(SC));1889 1890  SPIRVType *PointeeType = getPointeeType(PtrType);1891  MachineIRBuilder MIRBuilder(I);1892  return getOrCreateSPIRVPointerTypeInternal(PointeeType, MIRBuilder, SC);1893}1894 1895SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerType(1896    SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,1897    SPIRV::StorageClass::StorageClass SC) {1898  const Type *LLVMType = getTypeForSPIRVType(BaseType);1899  assert(!storageClassRequiresExplictLayout(SC));1900  SPIRVType *R = getOrCreateSPIRVPointerType(LLVMType, MIRBuilder, SC);1901  assert(1902      getPointeeType(R) == BaseType &&1903      "The base type was not correctly laid out for the given storage class.");1904  return R;1905}1906 1907SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVPointerTypeInternal(1908    SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,1909    SPIRV::StorageClass::StorageClass SC) {1910  const Type *PointerElementType = getTypeForSPIRVType(BaseType);1911  unsigned AddressSpace = storageClassToAddressSpace(SC);1912  if (const MachineInstr *MI = findMI(PointerElementType, AddressSpace, CurMF))1913    return MI;1914  Type *Ty = TypedPointerType::get(const_cast<Type *>(PointerElementType),1915                                   AddressSpace);1916  const MachineInstr *NewMI =1917      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1918        return BuildMI(MIRBuilder.getMBB(), MIRBuilder.getInsertPt(),1919                       MIRBuilder.getDebugLoc(),1920                       MIRBuilder.getTII().get(SPIRV::OpTypePointer))1921            .addDef(createTypeVReg(CurMF->getRegInfo()))1922            .addImm(static_cast<uint32_t>(SC))1923            .addUse(getSPIRVTypeID(BaseType));1924      });1925  add(PointerElementType, AddressSpace, NewMI);1926  return finishCreatingSPIRVType(Ty, NewMI);1927}1928 1929Register SPIRVGlobalRegistry::getOrCreateUndef(MachineInstr &I,1930                                               SPIRVType *SpvType,1931                                               const SPIRVInstrInfo &TII) {1932  UndefValue *UV =1933      UndefValue::get(const_cast<Type *>(getTypeForSPIRVType(SpvType)));1934  Register Res = find(UV, CurMF);1935  if (Res.isValid())1936    return Res;1937 1938  LLT LLTy = LLT::scalar(64);1939  Res = CurMF->getRegInfo().createGenericVirtualRegister(LLTy);1940  CurMF->getRegInfo().setRegClass(Res, &SPIRV::iIDRegClass);1941  assignSPIRVTypeToVReg(SpvType, Res, *CurMF);1942 1943  MachineInstr *DepMI = const_cast<MachineInstr *>(SpvType);1944  MachineIRBuilder MIRBuilder(*DepMI->getParent(), DepMI->getIterator());1945  const MachineInstr *NewMI =1946      createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {1947        auto MIB = BuildMI(MIRBuilder.getMBB(), *MIRBuilder.getInsertPt(),1948                           MIRBuilder.getDL(), TII.get(SPIRV::OpUndef))1949                       .addDef(Res)1950                       .addUse(getSPIRVTypeID(SpvType));1951        const auto &ST = CurMF->getSubtarget();1952        constrainSelectedInstRegOperands(*MIB, *ST.getInstrInfo(),1953                                         *ST.getRegisterInfo(),1954                                         *ST.getRegBankInfo());1955        return MIB;1956      });1957  add(UV, NewMI);1958  return Res;1959}1960 1961const TargetRegisterClass *1962SPIRVGlobalRegistry::getRegClass(SPIRVType *SpvType) const {1963  unsigned Opcode = SpvType->getOpcode();1964  switch (Opcode) {1965  case SPIRV::OpTypeFloat:1966    return &SPIRV::fIDRegClass;1967  case SPIRV::OpTypePointer:1968    return &SPIRV::pIDRegClass;1969  case SPIRV::OpTypeVector: {1970    SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());1971    unsigned ElemOpcode = ElemType ? ElemType->getOpcode() : 0;1972    if (ElemOpcode == SPIRV::OpTypeFloat)1973      return &SPIRV::vfIDRegClass;1974    if (ElemOpcode == SPIRV::OpTypePointer)1975      return &SPIRV::vpIDRegClass;1976    return &SPIRV::vIDRegClass;1977  }1978  }1979  return &SPIRV::iIDRegClass;1980}1981 1982inline unsigned getAS(SPIRVType *SpvType) {1983  return storageClassToAddressSpace(1984      static_cast<SPIRV::StorageClass::StorageClass>(1985          SpvType->getOperand(1).getImm()));1986}1987 1988LLT SPIRVGlobalRegistry::getRegType(SPIRVType *SpvType) const {1989  unsigned Opcode = SpvType ? SpvType->getOpcode() : 0;1990  switch (Opcode) {1991  case SPIRV::OpTypeInt:1992  case SPIRV::OpTypeFloat:1993  case SPIRV::OpTypeBool:1994    return LLT::scalar(getScalarOrVectorBitWidth(SpvType));1995  case SPIRV::OpTypePointer:1996    return LLT::pointer(getAS(SpvType), getPointerSize());1997  case SPIRV::OpTypeVector: {1998    SPIRVType *ElemType = getSPIRVTypeForVReg(SpvType->getOperand(1).getReg());1999    LLT ET;2000    switch (ElemType ? ElemType->getOpcode() : 0) {2001    case SPIRV::OpTypePointer:2002      ET = LLT::pointer(getAS(ElemType), getPointerSize());2003      break;2004    case SPIRV::OpTypeInt:2005    case SPIRV::OpTypeFloat:2006    case SPIRV::OpTypeBool:2007      ET = LLT::scalar(getScalarOrVectorBitWidth(ElemType));2008      break;2009    default:2010      ET = LLT::scalar(64);2011    }2012    return LLT::fixed_vector(2013        static_cast<unsigned>(SpvType->getOperand(2).getImm()), ET);2014  }2015  }2016  return LLT::scalar(64);2017}2018 2019// Aliasing list MD contains several scope MD nodes whithin it. Each scope MD2020// has a selfreference and an extra MD node for aliasing domain and also it2021// can contain an optional string operand. Domain MD contains a self-reference2022// with an optional string operand. Here we unfold the list, creating SPIR-V2023// aliasing instructions.2024// TODO: add support for an optional string operand.2025MachineInstr *SPIRVGlobalRegistry::getOrAddMemAliasingINTELInst(2026    MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD) {2027  if (AliasingListMD->getNumOperands() == 0)2028    return nullptr;2029  if (auto L = AliasInstMDMap.find(AliasingListMD); L != AliasInstMDMap.end())2030    return L->second;2031 2032  SmallVector<MachineInstr *> ScopeList;2033  MachineRegisterInfo *MRI = MIRBuilder.getMRI();2034  for (const MDOperand &MDListOp : AliasingListMD->operands()) {2035    if (MDNode *ScopeMD = dyn_cast<MDNode>(MDListOp)) {2036      if (ScopeMD->getNumOperands() < 2)2037        return nullptr;2038      MDNode *DomainMD = dyn_cast<MDNode>(ScopeMD->getOperand(1));2039      if (!DomainMD)2040        return nullptr;2041      auto *Domain = [&] {2042        auto D = AliasInstMDMap.find(DomainMD);2043        if (D != AliasInstMDMap.end())2044          return D->second;2045        const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);2046        auto MIB =2047            MIRBuilder.buildInstr(SPIRV::OpAliasDomainDeclINTEL).addDef(Ret);2048        return MIB.getInstr();2049      }();2050      AliasInstMDMap.insert(std::make_pair(DomainMD, Domain));2051      auto *Scope = [&] {2052        auto S = AliasInstMDMap.find(ScopeMD);2053        if (S != AliasInstMDMap.end())2054          return S->second;2055        const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);2056        auto MIB = MIRBuilder.buildInstr(SPIRV::OpAliasScopeDeclINTEL)2057                       .addDef(Ret)2058                       .addUse(Domain->getOperand(0).getReg());2059        return MIB.getInstr();2060      }();2061      AliasInstMDMap.insert(std::make_pair(ScopeMD, Scope));2062      ScopeList.push_back(Scope);2063    }2064  }2065 2066  const Register Ret = MRI->createVirtualRegister(&SPIRV::IDRegClass);2067  auto MIB =2068      MIRBuilder.buildInstr(SPIRV::OpAliasScopeListDeclINTEL).addDef(Ret);2069  for (auto *Scope : ScopeList)2070    MIB.addUse(Scope->getOperand(0).getReg());2071  auto List = MIB.getInstr();2072  AliasInstMDMap.insert(std::make_pair(AliasingListMD, List));2073  return List;2074}2075 2076void SPIRVGlobalRegistry::buildMemAliasingOpDecorate(2077    Register Reg, MachineIRBuilder &MIRBuilder, uint32_t Dec,2078    const MDNode *AliasingListMD) {2079  MachineInstr *AliasList =2080      getOrAddMemAliasingINTELInst(MIRBuilder, AliasingListMD);2081  if (!AliasList)2082    return;2083  MIRBuilder.buildInstr(SPIRV::OpDecorate)2084      .addUse(Reg)2085      .addImm(Dec)2086      .addUse(AliasList->getOperand(0).getReg());2087}2088void SPIRVGlobalRegistry::replaceAllUsesWith(Value *Old, Value *New,2089                                             bool DeleteOld) {2090  Old->replaceAllUsesWith(New);2091  updateIfExistDeducedElementType(Old, New, DeleteOld);2092  updateIfExistAssignPtrTypeInstr(Old, New, DeleteOld);2093}2094 2095void SPIRVGlobalRegistry::buildAssignType(IRBuilder<> &B, Type *Ty,2096                                          Value *Arg) {2097  Value *OfType = getNormalizedPoisonValue(Ty);2098  CallInst *AssignCI = nullptr;2099  if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&2100      allowEmitFakeUse(Arg)) {2101    LLVMContext &Ctx = Arg->getContext();2102    SmallVector<Metadata *, 2> ArgMDs{2103        MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)),2104        MDString::get(Ctx, Arg->getName())};2105    B.CreateIntrinsic(Intrinsic::spv_value_md,2106                      {MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});2107    AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {Arg});2108  } else {2109    AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},2110                               OfType, Arg, {}, B);2111  }2112  addAssignPtrTypeInstr(Arg, AssignCI);2113}2114 2115void SPIRVGlobalRegistry::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,2116                                         Value *Arg) {2117  Value *OfType = PoisonValue::get(ElemTy);2118  CallInst *AssignPtrTyCI = findAssignPtrTypeInstr(Arg);2119  Function *CurrF =2120      B.GetInsertBlock() ? B.GetInsertBlock()->getParent() : nullptr;2121  if (AssignPtrTyCI == nullptr ||2122      AssignPtrTyCI->getParent()->getParent() != CurrF) {2123    AssignPtrTyCI = buildIntrWithMD(2124        Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,2125        {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);2126    addDeducedElementType(AssignPtrTyCI, ElemTy);2127    addDeducedElementType(Arg, ElemTy);2128    addAssignPtrTypeInstr(Arg, AssignPtrTyCI);2129  } else {2130    updateAssignType(AssignPtrTyCI, Arg, OfType);2131  }2132}2133 2134void SPIRVGlobalRegistry::updateAssignType(CallInst *AssignCI, Value *Arg,2135                                           Value *OfType) {2136  AssignCI->setArgOperand(1, buildMD(OfType));2137  if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=2138      Intrinsic::spv_assign_ptr_type)2139    return;2140 2141  // update association with the pointee type2142  Type *ElemTy = OfType->getType();2143  addDeducedElementType(AssignCI, ElemTy);2144  addDeducedElementType(Arg, ElemTy);2145}2146 2147void SPIRVGlobalRegistry::addStructOffsetDecorations(2148    Register Reg, StructType *Ty, MachineIRBuilder &MIRBuilder) {2149  DataLayout DL;2150  ArrayRef<TypeSize> Offsets = DL.getStructLayout(Ty)->getMemberOffsets();2151  for (uint32_t I = 0; I < Ty->getNumElements(); ++I) {2152    buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,2153                          {static_cast<uint32_t>(Offsets[I])});2154  }2155}2156 2157void SPIRVGlobalRegistry::addArrayStrideDecorations(2158    Register Reg, Type *ElementType, MachineIRBuilder &MIRBuilder) {2159  uint32_t SizeInBytes = DataLayout().getTypeSizeInBits(ElementType) / 8;2160  buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::ArrayStride,2161                  {SizeInBytes});2162}2163 2164bool SPIRVGlobalRegistry::hasBlockDecoration(SPIRVType *Type) const {2165  Register Def = getSPIRVTypeID(Type);2166  for (const MachineInstr &Use :2167       Type->getMF()->getRegInfo().use_instructions(Def)) {2168    if (Use.getOpcode() != SPIRV::OpDecorate)2169      continue;2170 2171    if (Use.getOperand(1).getImm() == SPIRV::Decoration::Block)2172      return true;2173  }2174  return false;2175}2176