brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.4 KiB · e5a1a2a Raw
668 lines · c
1//===-- SPIRVGlobalRegistry.h - 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// SPIRVGlobalRegistry is used to maintain rich type information required for10// SPIR-V even after lowering from LLVM IR to GMIR. It can convert an llvm::Type11// into an OpTypeXXX instruction, and map it to a virtual register. Also it12// builds and supports consistency of constants and global variables.13//14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H17#define LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H18 19#include "MCTargetDesc/SPIRVBaseInfo.h"20#include "SPIRVIRMapping.h"21#include "SPIRVInstrInfo.h"22#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"23#include "llvm/IR/Constant.h"24#include "llvm/IR/TypedPointerType.h"25 26namespace llvm {27class SPIRVSubtarget;28using SPIRVType = const MachineInstr;29using StructOffsetDecorator = std::function<void(Register)>;30 31class SPIRVGlobalRegistry : public SPIRVIRMapping {32  // Registers holding values which have types associated with them.33  // Initialized upon VReg definition in IRTranslator.34  // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>35  // where Reg = OpType...36  // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not37  // type-declaring ones).38  DenseMap<const MachineFunction *, DenseMap<Register, SPIRVType *>>39      VRegToTypeMap;40 41  DenseMap<SPIRVType *, const Type *> SPIRVToLLVMType;42 43  // map a Function to its definition (as a machine instruction operand)44  DenseMap<const Function *, const MachineOperand *> FunctionToInstr;45  DenseMap<const MachineInstr *, const Function *> FunctionToInstrRev;46  // map function pointer (as a machine instruction operand) to the used47  // Function48  DenseMap<const MachineOperand *, const Function *> InstrToFunction;49  // Maps Functions to their calls (in a form of the machine instruction,50  // OpFunctionCall) that happened before the definition is available51  DenseMap<const Function *, SmallPtrSet<MachineInstr *, 8>> ForwardCalls;52  // map a Function to its original return type before the clone function was53  // created during substitution of aggregate arguments54  // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`)55  DenseMap<Value *, Type *> MutatedAggRet;56  // map an instruction to its value's attributes (type, name)57  DenseMap<MachineInstr *, std::pair<Type *, std::string>> ValueAttrs;58 59  SmallPtrSet<const Type *, 4> TypesInProcessing;60  DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;61 62  // Stores for each function the last inserted SPIR-V Type.63  // See: SPIRVGlobalRegistry::createOpType.64  DenseMap<const MachineFunction *, MachineInstr *> LastInsertedTypeMap;65 66  // if a function returns a pointer, this is to map it into TypedPointerType67  DenseMap<const Function *, TypedPointerType *> FunResPointerTypes;68 69  // Number of bits pointers and size_t integers require.70  const unsigned PointerSize;71 72  // Holds the maximum ID we have in the module.73  unsigned Bound;74 75  // Maps values associated with untyped pointers into deduced element types of76  // untyped pointers.77  DenseMap<Value *, Type *> DeducedElTys;78  // Maps composite values to deduced types where untyped pointers are replaced79  // with typed ones.80  DenseMap<Value *, Type *> DeducedNestedTys;81  // Maps values to "assign type" calls, thus being a registry of created82  // Intrinsic::spv_assign_ptr_type instructions.83  DenseMap<Value *, CallInst *> AssignPtrTypeInstr;84 85  // Maps OpVariable and OpFunction-related v-regs to its LLVM IR definition.86  DenseMap<std::pair<const MachineFunction *, Register>, const Value *> Reg2GO;87 88  // map of aliasing decorations to aliasing metadata89  std::unordered_map<const MDNode *, MachineInstr *> AliasInstMDMap;90 91  // Add a new OpTypeXXX instruction without checking for duplicates.92  SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,93                             SPIRV::AccessQualifier::AccessQualifier AQ,94                             bool ExplicitLayoutRequired, bool EmitIR);95  SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,96                           SPIRV::AccessQualifier::AccessQualifier accessQual,97                           bool ExplicitLayoutRequired, bool EmitIR);98  SPIRVType *99  restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,100                        SPIRV::AccessQualifier::AccessQualifier AccessQual,101                        bool ExplicitLayoutRequired, bool EmitIR);102 103  // Internal function creating the an OpType at the correct position in the104  // function by tweaking the passed "MIRBuilder" insertion point and restoring105  // it to the correct position. "Op" should be the function creating the106  // specific OpType you need, and should return the newly created instruction.107  SPIRVType *createOpType(MachineIRBuilder &MIRBuilder,108                          std::function<MachineInstr *(MachineIRBuilder &)> Op);109 110public:111  SPIRVGlobalRegistry(unsigned PointerSize);112 113  MachineFunction *CurMF;114 115  void setBound(unsigned V) { Bound = V; }116  unsigned getBound() { return Bound; }117 118  void addGlobalObject(const Value *V, const MachineFunction *MF, Register R) {119    Reg2GO[std::make_pair(MF, R)] = V;120  }121  const Value *getGlobalObject(const MachineFunction *MF, Register R) {122    auto It = Reg2GO.find(std::make_pair(MF, R));123    return It == Reg2GO.end() ? nullptr : It->second;124  }125 126  // Add a record to the map of function return pointer types.127  void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) {128    FunResPointerTypes[ArgF] = DerivedTy;129  }130  // Find a record in the map of function return pointer types.131  const TypedPointerType *findReturnType(const Function *ArgF) {132    auto It = FunResPointerTypes.find(ArgF);133    return It == FunResPointerTypes.end() ? nullptr : It->second;134  }135 136  // A registry of "assign type" records:137  // - Add a record.138  void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) {139    AssignPtrTypeInstr[Val] = AssignPtrTyCI;140  }141  // - Find a record.142  CallInst *findAssignPtrTypeInstr(const Value *Val) {143    auto It = AssignPtrTypeInstr.find(Val);144    return It == AssignPtrTypeInstr.end() ? nullptr : It->second;145  }146  // - Find a record and update its key or add a new record, if found.147  void updateIfExistAssignPtrTypeInstr(Value *OldVal, Value *NewVal,148                                       bool DeleteOld) {149    if (CallInst *CI = findAssignPtrTypeInstr(OldVal)) {150      if (DeleteOld)151        AssignPtrTypeInstr.erase(OldVal);152      AssignPtrTypeInstr[NewVal] = CI;153    }154  }155 156  // A registry of mutated values157  // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`):158  // - Add a record.159  void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; }160  // - Find a record.161  Type *findMutated(const Value *Val) {162    auto It = MutatedAggRet.find(Val);163    return It == MutatedAggRet.end() ? nullptr : It->second;164  }165 166  // A registry of value's attributes (type, name)167  // - Add a record.168  void addValueAttrs(MachineInstr *Key, std::pair<Type *, std::string> Val) {169    ValueAttrs[Key] = Val;170  }171  // - Find a record.172  bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name) {173    auto It = ValueAttrs.find(Key);174    if (It == ValueAttrs.end())175      return false;176    Ty = It->second.first;177    Name = It->second.second;178    return true;179  }180 181  // Deduced element types of untyped pointers and composites:182  // - Add a record to the map of deduced element types.183  void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }184  // - Find a record in the map of deduced element types.185  Type *findDeducedElementType(const Value *Val) {186    auto It = DeducedElTys.find(Val);187    return It == DeducedElTys.end() ? nullptr : It->second;188  }189  // - Find a record and update its key or add a new record, if found.190  void updateIfExistDeducedElementType(Value *OldVal, Value *NewVal,191                                       bool DeleteOld) {192    if (Type *Ty = findDeducedElementType(OldVal)) {193      if (DeleteOld)194        DeducedElTys.erase(OldVal);195      DeducedElTys[NewVal] = Ty;196    }197  }198  // - Add a record to the map of deduced composite types.199  void addDeducedCompositeType(Value *Val, Type *Ty) {200    DeducedNestedTys[Val] = Ty;201  }202  // - Find a record in the map of deduced composite types.203  Type *findDeducedCompositeType(const Value *Val) {204    auto It = DeducedNestedTys.find(Val);205    return It == DeducedNestedTys.end() ? nullptr : It->second;206  }207  // - Find a type of the given Global value208  Type *getDeducedGlobalValueType(const GlobalValue *Global) {209    // we may know element type if it was deduced earlier210    Type *ElementTy = findDeducedElementType(Global);211    if (!ElementTy) {212      // or we may know element type if it's associated with a composite213      // value214      if (Value *GlobalElem =215              Global->getNumOperands() > 0 ? Global->getOperand(0) : nullptr)216        ElementTy = findDeducedCompositeType(GlobalElem);217    }218    return ElementTy ? ElementTy : Global->getValueType();219  }220 221  // Map a machine operand that represents a use of a function via function222  // pointer to a machine operand that represents the function definition.223  // Return either the register or invalid value, because we have no context for224  // a good diagnostic message in case of unexpectedly missing references.225  const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) {226    auto ResF = InstrToFunction.find(Use);227    if (ResF == InstrToFunction.end())228      return nullptr;229    auto ResReg = FunctionToInstr.find(ResF->second);230    return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;231  }232 233  // Map a Function to a machine instruction that represents the function234  // definition.235  const MachineInstr *getFunctionDefinition(const Function *F) {236    if (!F)237      return nullptr;238    auto MOIt = FunctionToInstr.find(F);239    return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent();240  }241 242  // Map a Function to a machine instruction that represents the function243  // definition.244  const Function *getFunctionByDefinition(const MachineInstr *MI) {245    if (!MI)246      return nullptr;247    auto FIt = FunctionToInstrRev.find(MI);248    return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second;249  }250 251  // map function pointer (as a machine instruction operand) to the used252  // Function253  void recordFunctionPointer(const MachineOperand *MO, const Function *F) {254    InstrToFunction[MO] = F;255  }256 257  // map a Function to its definition (as a machine instruction)258  void recordFunctionDefinition(const Function *F, const MachineOperand *MO) {259    FunctionToInstr[F] = MO;260    FunctionToInstrRev[MO->getParent()] = F;261  }262 263  // Return true if any OpConstantFunctionPointerINTEL were generated264  bool hasConstFunPtr() { return !InstrToFunction.empty(); }265 266  // Add a record about forward function call.267  void addForwardCall(const Function *F, MachineInstr *MI) {268    ForwardCalls[F].insert(MI);269  }270 271  // Map a Function to the vector of machine instructions that represents272  // forward function calls or to nullptr if not found.273  SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) {274    auto It = ForwardCalls.find(F);275    return It == ForwardCalls.end() ? nullptr : &It->second;276  }277 278  // Get or create a SPIR-V type corresponding the given LLVM IR type,279  // and map it to the given VReg by creating an ASSIGN_TYPE instruction.280  SPIRVType *assignTypeToVReg(const Type *Type, Register VReg,281                              MachineIRBuilder &MIRBuilder,282                              SPIRV::AccessQualifier::AccessQualifier AQ,283                              bool EmitIR);284  SPIRVType *assignIntTypeToVReg(unsigned BitWidth, Register VReg,285                                 MachineInstr &I, const SPIRVInstrInfo &TII);286  SPIRVType *assignFloatTypeToVReg(unsigned BitWidth, Register VReg,287                                   MachineInstr &I, const SPIRVInstrInfo &TII);288  SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements,289                                  Register VReg, MachineInstr &I,290                                  const SPIRVInstrInfo &TII);291 292  // In cases where the SPIR-V type is already known, this function can be293  // used to map it to the given VReg via an ASSIGN_TYPE instruction.294  void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg,295                             const MachineFunction &MF);296 297  // Either generate a new OpTypeXXX instruction or return an existing one298  // corresponding to the given LLVM IR type.299  // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)300  // because this method may be called from InstructionSelector and we don't301  // want to emit extra IR instructions there.302  SPIRVType *getOrCreateSPIRVType(const Type *Type, MachineInstr &I,303                                  SPIRV::AccessQualifier::AccessQualifier AQ,304                                  bool EmitIR) {305    MachineIRBuilder MIRBuilder(I);306    return getOrCreateSPIRVType(Type, MIRBuilder, AQ, EmitIR);307  }308 309  SPIRVType *getOrCreateSPIRVType(const Type *Type,310                                  MachineIRBuilder &MIRBuilder,311                                  SPIRV::AccessQualifier::AccessQualifier AQ,312                                  bool EmitIR) {313    return getOrCreateSPIRVType(Type, MIRBuilder, AQ, false, EmitIR);314  }315 316  const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {317    auto Res = SPIRVToLLVMType.find(Ty);318    assert(Res != SPIRVToLLVMType.end());319    return Res->second;320  }321 322  // Return a pointee's type, or nullptr otherwise.323  SPIRVType *getPointeeType(SPIRVType *PtrType);324  // Return a pointee's type op code, or 0 otherwise.325  unsigned getPointeeTypeOp(Register PtrReg);326 327  // Either generate a new OpTypeXXX instruction or return an existing one328  // corresponding to the given string containing the name of the builtin type.329  // Return nullptr if unable to recognize SPIRV type name from `TypeStr`.330  SPIRVType *getOrCreateSPIRVTypeByName(331      StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR,332      SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,333      SPIRV::AccessQualifier::AccessQualifier AQ =334          SPIRV::AccessQualifier::ReadWrite);335 336  // Return the SPIR-V type instruction corresponding to the given VReg, or337  // nullptr if no such type instruction exists. The second argument MF338  // allows to search for the association in a context of the machine functions339  // than the current one, without switching between different "current" machine340  // functions.341  SPIRVType *getSPIRVTypeForVReg(Register VReg,342                                 const MachineFunction *MF = nullptr) const;343 344  // Return the result type of the instruction defining the register.345  SPIRVType *getResultType(Register VReg, MachineFunction *MF = nullptr);346 347  // Whether the given VReg has a SPIR-V type mapped to it yet.348  bool hasSPIRVTypeForVReg(Register VReg) const {349    return getSPIRVTypeForVReg(VReg) != nullptr;350  }351 352  // Return the VReg holding the result of the given OpTypeXXX instruction.353  Register getSPIRVTypeID(const SPIRVType *SpirvType) const;354 355  // Return previous value of the current machine function356  MachineFunction *setCurrentFunc(MachineFunction &MF) {357    MachineFunction *Ret = CurMF;358    CurMF = &MF;359    return Ret;360  }361 362  // Return true if the type is an aggregate type.363  bool isAggregateType(SPIRVType *Type) const {364    return Type && (Type->getOpcode() == SPIRV::OpTypeStruct &&365                    Type->getOpcode() == SPIRV::OpTypeArray);366  }367 368  // Whether the given VReg has an OpTypeXXX instruction mapped to it with the369  // given opcode (e.g. OpTypeFloat).370  bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;371 372  // Return true if the given VReg's assigned SPIR-V type is either a scalar373  // matching the given opcode, or a vector with an element type matching that374  // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).375  bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;376 377  // Returns true if `Type` is a resource type. This could be an image type378  // or a struct for a buffer decorated with the block decoration.379  bool isResourceType(SPIRVType *Type) const;380 381  // Return number of elements in a vector if the argument is associated with382  // a vector type. Return 1 for a scalar type, and 0 for a missing type.383  unsigned getScalarOrVectorComponentCount(Register VReg) const;384  unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const;385 386  // Return the component type in a vector if the argument is associated with387  // a vector type. Returns the argument itself for other types, and nullptr388  // for a missing type.389  SPIRVType *getScalarOrVectorComponentType(Register VReg) const;390  SPIRVType *getScalarOrVectorComponentType(SPIRVType *Type) const;391 392  // For vectors or scalars of booleans, integers and floats, return the scalar393  // type's bitwidth. Otherwise calls llvm_unreachable().394  unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;395 396  // For vectors or scalars of integers and floats, return total bitwidth of the397  // argument. Otherwise returns 0.398  unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const;399 400  // Returns either pointer to integer type, that may be a type of vector401  // elements or an original type, or nullptr if the argument is niether402  // an integer scalar, nor an integer vector403  const SPIRVType *retrieveScalarOrVectorIntType(const SPIRVType *Type) const;404 405  // For integer vectors or scalars, return whether the integers are signed.406  bool isScalarOrVectorSigned(const SPIRVType *Type) const;407 408  // Gets the storage class of the pointer type assigned to this vreg.409  SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;410  SPIRV::StorageClass::StorageClass411  getPointerStorageClass(const SPIRVType *Type) const;412 413  // Return the number of bits SPIR-V pointers and size_t variables require.414  unsigned getPointerSize() const { return PointerSize; }415 416  // Returns true if two types are defined and are compatible in a sense of417  // OpBitcast instruction418  bool isBitcastCompatible(const SPIRVType *Type1,419                           const SPIRVType *Type2) const;420 421  // Informs about removal of the machine instruction and invalidates data422  // structures referring this instruction.423  void invalidateMachineInstr(MachineInstr *MI);424 425private:426  SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);427 428  const Type *adjustIntTypeByWidth(const Type *Ty) const;429  unsigned adjustOpTypeIntWidth(unsigned Width) const;430 431  SPIRVType *getOrCreateSPIRVType(const Type *Type,432                                  MachineIRBuilder &MIRBuilder,433                                  SPIRV::AccessQualifier::AccessQualifier AQ,434                                  bool ExplicitLayoutRequired, bool EmitIR);435 436  SPIRVType *getOpTypeInt(unsigned Width, MachineIRBuilder &MIRBuilder,437                          bool IsSigned = false);438 439  SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);440 441  SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder,442                            SPIRV::FPEncoding::FPEncoding FPEncode);443 444  SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder);445 446  SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType,447                             MachineIRBuilder &MIRBuilder);448 449  SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType,450                            MachineIRBuilder &MIRBuilder,451                            bool ExplicitLayoutRequired, bool EmitIR);452 453  SPIRVType *getOpTypeOpaque(const StructType *Ty,454                             MachineIRBuilder &MIRBuilder);455 456  SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,457                             SPIRV::AccessQualifier::AccessQualifier AccQual,458                             StructOffsetDecorator Decorator, bool EmitIR);459 460  SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,461                              SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,462                              Register Reg);463 464  SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,465                                     MachineIRBuilder &MIRBuilder);466 467  SPIRVType *getOpTypeFunction(const FunctionType *Ty, SPIRVType *RetType,468                               const SmallVectorImpl<SPIRVType *> &ArgTypes,469                               MachineIRBuilder &MIRBuilder);470 471  SPIRVType *472  getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,473                         SPIRV::AccessQualifier::AccessQualifier AccQual);474 475  SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);476  Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I,477                                   SPIRVType *SpvType,478                                   const SPIRVInstrInfo &TII, unsigned BitWidth,479                                   bool ZeroAsNull);480  Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I,481                                      SPIRVType *SpvType,482                                      const SPIRVInstrInfo &TII, Constant *CA,483                                      unsigned BitWidth, unsigned ElemCnt,484                                      bool ZeroAsNull = true);485 486  Register getOrCreateIntCompositeOrNull(uint64_t Val,487                                         MachineIRBuilder &MIRBuilder,488                                         SPIRVType *SpvType, bool EmitIR,489                                         Constant *CA, unsigned BitWidth,490                                         unsigned ElemCnt);491 492  // Returns a pointer to a SPIR-V pointer type with the given base type and493  // storage class. It is the responsibility of the caller to make sure the494  // decorations on the base type are valid for the given storage class. For495  // example, it has the correct offset and stride decorations.496  SPIRVType *497  getOrCreateSPIRVPointerTypeInternal(SPIRVType *BaseType,498                                      MachineIRBuilder &MIRBuilder,499                                      SPIRV::StorageClass::StorageClass SC);500 501  void addStructOffsetDecorations(Register Reg, StructType *Ty,502                                  MachineIRBuilder &MIRBuilder);503  void addArrayStrideDecorations(Register Reg, Type *ElementType,504                                 MachineIRBuilder &MIRBuilder);505  bool hasBlockDecoration(SPIRVType *Type) const;506 507  SPIRVType *508  getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,509                         SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,510                         uint32_t Multisampled, uint32_t Sampled,511                         SPIRV::ImageFormat::ImageFormat ImageFormat,512                         SPIRV::AccessQualifier::AccessQualifier AccQual);513 514public:515  Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder,516                            SPIRVType *SpvType, bool EmitIR,517                            bool ZeroAsNull = true);518  Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,519                               SPIRVType *SpvType, const SPIRVInstrInfo &TII,520                               bool ZeroAsNull = true);521  Register createConstInt(const ConstantInt *CI, MachineInstr &I,522                          SPIRVType *SpvType, const SPIRVInstrInfo &TII,523                          bool ZeroAsNull);524  Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType,525                              const SPIRVInstrInfo &TII,526                              bool ZeroAsNull = true);527  Register createConstFP(const ConstantFP *CF, MachineInstr &I,528                         SPIRVType *SpvType, const SPIRVInstrInfo &TII,529                         bool ZeroAsNull);530  Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder,531                           SPIRVType *SpvType = nullptr);532 533  Register getOrCreateConstVector(uint64_t Val, MachineInstr &I,534                                  SPIRVType *SpvType, const SPIRVInstrInfo &TII,535                                  bool ZeroAsNull = true);536  Register getOrCreateConstVector(APFloat Val, MachineInstr &I,537                                  SPIRVType *SpvType, const SPIRVInstrInfo &TII,538                                  bool ZeroAsNull = true);539  Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I,540                                    SPIRVType *SpvType,541                                    const SPIRVInstrInfo &TII);542  Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder,543                                    SPIRVType *SpvType, bool EmitIR);544  Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,545                                   SPIRVType *SpvType);546  Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,547                                unsigned FilerMode,548                                MachineIRBuilder &MIRBuilder);549  Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType,550                            const SPIRVInstrInfo &TII);551  Register buildGlobalVariable(552      Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV,553      SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init,554      bool IsConst,555      const std::optional<SPIRV::LinkageType::LinkageType> &LinkageType,556      MachineIRBuilder &MIRBuilder, bool IsInstSelector);557  Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType,558                                                uint32_t Set, uint32_t Binding,559                                                StringRef Name,560                                                MachineIRBuilder &MIRBuilder);561 562  // Convenient helpers for getting types with check for duplicates.563  SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth,564                                         MachineIRBuilder &MIRBuilder);565  SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I,566                                         const SPIRVInstrInfo &TII);567  SPIRVType *getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I,568                                  const SPIRVInstrInfo &TII,569                                  unsigned SPIRVOPcode, Type *LLVMTy);570  SPIRVType *getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I,571                                       const SPIRVInstrInfo &TII);572  SPIRVType *getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder,573                                      bool EmitIR);574  SPIRVType *getOrCreateSPIRVBoolType(MachineInstr &I,575                                      const SPIRVInstrInfo &TII);576  SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,577                                        unsigned NumElements,578                                        MachineIRBuilder &MIRBuilder,579                                        bool EmitIR);580  SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,581                                        unsigned NumElements, MachineInstr &I,582                                        const SPIRVInstrInfo &TII);583 584  // Returns a pointer to a SPIR-V pointer type with the given base type and585  // storage class. The base type will be translated to a SPIR-V type, and the586  // appropriate layout decorations will be added to the base type.587  SPIRVType *getOrCreateSPIRVPointerType(const Type *BaseType,588                                         MachineIRBuilder &MIRBuilder,589                                         SPIRV::StorageClass::StorageClass SC);590  SPIRVType *getOrCreateSPIRVPointerType(const Type *BaseType, MachineInstr &I,591                                         SPIRV::StorageClass::StorageClass SC);592 593  // Returns a pointer to a SPIR-V pointer type with the given base type and594  // storage class. It is the responsibility of the caller to make sure the595  // decorations on the base type are valid for the given storage class. For596  // example, it has the correct offset and stride decorations.597  SPIRVType *getOrCreateSPIRVPointerType(SPIRVType *BaseType,598                                         MachineIRBuilder &MIRBuilder,599                                         SPIRV::StorageClass::StorageClass SC);600 601  // Returns a pointer to a SPIR-V pointer type that is the same as `PtrType`602  // except the stroage class has been changed to `SC`. It is the responsibility603  // of the caller to be sure that the original and new storage class have the604  // same layout requirements.605  SPIRVType *changePointerStorageClass(SPIRVType *PtrType,606                                       SPIRV::StorageClass::StorageClass SC,607                                       MachineInstr &I);608 609  SPIRVType *getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder,610                                         Type *ElemType,611                                         SPIRV::StorageClass::StorageClass SC,612                                         bool IsWritable, bool EmitIr = false);613 614  SPIRVType *getOrCreatePaddingType(MachineIRBuilder &MIRBuilder);615 616  SPIRVType *getOrCreateLayoutType(MachineIRBuilder &MIRBuilder,617                                   const TargetExtType *T, bool EmitIr = false);618 619  SPIRVType *620  getImageType(const TargetExtType *ExtensionType,621               const SPIRV::AccessQualifier::AccessQualifier Qualifier,622               MachineIRBuilder &MIRBuilder);623 624  SPIRVType *getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder);625 626  SPIRVType *getOrCreateOpTypeSampledImage(SPIRVType *ImageType,627                                           MachineIRBuilder &MIRBuilder);628  SPIRVType *getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder,629                                       const TargetExtType *ExtensionType,630                                       const SPIRVType *ElemType,631                                       uint32_t Scope, uint32_t Rows,632                                       uint32_t Columns, uint32_t Use,633                                       bool EmitIR);634  SPIRVType *635  getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder,636                        SPIRV::AccessQualifier::AccessQualifier AccQual);637  SPIRVType *getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder);638  SPIRVType *getOrCreateOpTypeFunctionWithArgs(639      const Type *Ty, SPIRVType *RetType,640      const SmallVectorImpl<SPIRVType *> &ArgTypes,641      MachineIRBuilder &MIRBuilder);642  SPIRVType *getOrCreateOpTypeByOpcode(const Type *Ty,643                                       MachineIRBuilder &MIRBuilder,644                                       unsigned Opcode);645 646  SPIRVType *getOrCreateUnknownType(const Type *Ty,647                                    MachineIRBuilder &MIRBuilder,648                                    unsigned Opcode,649                                    const ArrayRef<MCOperand> Operands);650 651  const TargetRegisterClass *getRegClass(SPIRVType *SpvType) const;652  LLT getRegType(SPIRVType *SpvType) const;653 654  MachineInstr *getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder,655                                             const MDNode *AliasingListMD);656  void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder,657                                  uint32_t Dec, const MDNode *GVarMD);658  // Replace all uses of a |Old| with |New| updates the global registry type659  // mappings.660  void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld = true);661 662  void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg);663  void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg);664  void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType);665};666} // end namespace llvm667#endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H668