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