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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // SPIRVGlobalRegistry is used to maintain rich type information required for 10 // SPIR-V even after lowering from LLVM IR to GMIR. It can convert an llvm::Type 11 // into an OpTypeXXX instruction, and map it to a virtual register. Also it 12 // builds and supports consistency of constants and global variables. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H 17 #define LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H 18 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 26 namespace llvm { 27 class SPIRVSubtarget; 28 using SPIRVType = const MachineInstr; 29 using StructOffsetDecorator = std::function<void(Register)>; 30 31 class 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. not 37 // 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 used 47 // Function 48 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 available 51 DenseMap<const Function *, SmallPtrSet<MachineInstr *, 8>> ForwardCalls; 52 // map a Function to its original return type before the clone function was 53 // created during substitution of aggregate arguments 54 // (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 TypedPointerType 67 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 of 76 // untyped pointers. 77 DenseMap<Value *, Type *> DeducedElTys; 78 // Maps composite values to deduced types where untyped pointers are replaced 79 // with typed ones. 80 DenseMap<Value *, Type *> DeducedNestedTys; 81 // Maps values to "assign type" calls, thus being a registry of created 82 // 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 metadata 89 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 the 104 // function by tweaking the passed "MIRBuilder" insertion point and restoring 105 // it to the correct position. "Op" should be the function creating the 106 // specific OpType you need, and should return the newly created instruction. 107 SPIRVType *createOpType(MachineIRBuilder &MIRBuilder, 108 std::function<MachineInstr *(MachineIRBuilder &)> Op); 109 110 public: 111 SPIRVGlobalRegistry(unsigned PointerSize); 112 113 MachineFunction *CurMF; 114 setBound(unsigned V)115 void setBound(unsigned V) { Bound = V; } getBound()116 unsigned getBound() { return Bound; } 117 addGlobalObject(const Value * V,const MachineFunction * MF,Register R)118 void addGlobalObject(const Value *V, const MachineFunction *MF, Register R) { 119 Reg2GO[std::make_pair(MF, R)] = V; 120 } getGlobalObject(const MachineFunction * MF,Register R)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. addReturnType(const Function * ArgF,TypedPointerType * DerivedTy)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. findReturnType(const Function * ArgF)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. addAssignPtrTypeInstr(Value * Val,CallInst * AssignPtrTyCI)138 void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) { 139 AssignPtrTypeInstr[Val] = AssignPtrTyCI; 140 } 141 // - Find a record. findAssignPtrTypeInstr(const Value * Val)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. updateIfExistAssignPtrTypeInstr(Value * OldVal,Value * NewVal,bool DeleteOld)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 values 157 // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`): 158 // - Add a record. addMutated(Value * Val,Type * Ty)159 void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; } 160 // - Find a record. findMutated(const Value * Val)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. addValueAttrs(MachineInstr * Key,std::pair<Type *,std::string> Val)168 void addValueAttrs(MachineInstr *Key, std::pair<Type *, std::string> Val) { 169 ValueAttrs[Key] = Val; 170 } 171 // - Find a record. findValueAttrs(const MachineInstr * Key,Type * & Ty,StringRef & Name)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. addDeducedElementType(Value * Val,Type * Ty)183 void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; } 184 // - Find a record in the map of deduced element types. findDeducedElementType(const Value * Val)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. updateIfExistDeducedElementType(Value * OldVal,Value * NewVal,bool DeleteOld)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. addDeducedCompositeType(Value * Val,Type * Ty)199 void addDeducedCompositeType(Value *Val, Type *Ty) { 200 DeducedNestedTys[Val] = Ty; 201 } 202 // - Find a record in the map of deduced composite types. findDeducedCompositeType(const Value * Val)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 value getDeducedGlobalValueType(const GlobalValue * Global)208 Type *getDeducedGlobalValueType(const GlobalValue *Global) { 209 // we may know element type if it was deduced earlier 210 Type *ElementTy = findDeducedElementType(Global); 211 if (!ElementTy) { 212 // or we may know element type if it's associated with a composite 213 // value 214 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 function 222 // pointer to a machine operand that represents the function definition. 223 // Return either the register or invalid value, because we have no context for 224 // a good diagnostic message in case of unexpectedly missing references. getFunctionDefinitionByUse(const MachineOperand * Use)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 function 234 // definition. getFunctionDefinition(const Function * F)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 function 243 // definition. getFunctionByDefinition(const MachineInstr * MI)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 used 252 // Function recordFunctionPointer(const MachineOperand * MO,const Function * F)253 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) recordFunctionDefinition(const Function * F,const MachineOperand * MO)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 generated hasConstFunPtr()264 bool hasConstFunPtr() { return !InstrToFunction.empty(); } 265 266 // Add a record about forward function call. addForwardCall(const Function * F,MachineInstr * MI)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 represents 272 // forward function calls or to nullptr if not found. getForwardCalls(const Function * F)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 be 293 // 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 one 298 // 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't 301 // want to emit extra IR instructions there. getOrCreateSPIRVType(const Type * Type,MachineInstr & I,SPIRV::AccessQualifier::AccessQualifier AQ,bool EmitIR)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 getOrCreateSPIRVType(const Type * Type,MachineIRBuilder & MIRBuilder,SPIRV::AccessQualifier::AccessQualifier AQ,bool EmitIR)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 getTypeForSPIRVType(const SPIRVType * Ty)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 one 328 // 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, or 337 // nullptr if no such type instruction exists. The second argument MF 338 // allows to search for the association in a context of the machine functions 339 // than the current one, without switching between different "current" machine 340 // 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. hasSPIRVTypeForVReg(Register VReg)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 function setCurrentFunc(MachineFunction & MF)356 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. isAggregateType(SPIRVType * 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 the 369 // 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 scalar 373 // matching the given opcode, or a vector with an element type matching that 374 // 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 type 378 // 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 with 382 // 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 with 387 // a vector type. Returns the argument itself for other types, and nullptr 388 // 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 scalar 393 // 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 the 397 // 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 vector 401 // elements or an original type, or nullptr if the argument is niether 402 // an integer scalar, nor an integer vector 403 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::StorageClass 411 getPointerStorageClass(const SPIRVType *Type) const; 412 413 // Return the number of bits SPIR-V pointers and size_t variables require. getPointerSize()414 unsigned getPointerSize() const { return PointerSize; } 415 416 // Returns true if two types are defined and are compatible in a sense of 417 // OpBitcast instruction 418 bool isBitcastCompatible(const SPIRVType *Type1, 419 const SPIRVType *Type2) const; 420 421 // Informs about removal of the machine instruction and invalidates data 422 // structures referring this instruction. 423 void invalidateMachineInstr(MachineInstr *MI); 424 425 private: 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 *getOpTypeVoid(MachineIRBuilder &MIRBuilder); 442 443 SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType, 444 MachineIRBuilder &MIRBuilder); 445 446 SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType, 447 MachineIRBuilder &MIRBuilder, 448 bool ExplicitLayoutRequired, bool EmitIR); 449 450 SPIRVType *getOpTypeOpaque(const StructType *Ty, 451 MachineIRBuilder &MIRBuilder); 452 453 SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder, 454 SPIRV::AccessQualifier::AccessQualifier AccQual, 455 StructOffsetDecorator Decorator, bool EmitIR); 456 457 SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC, 458 SPIRVType *ElemType, MachineIRBuilder &MIRBuilder, 459 Register Reg); 460 461 SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC, 462 MachineIRBuilder &MIRBuilder); 463 464 SPIRVType *getOpTypeFunction(SPIRVType *RetType, 465 const SmallVectorImpl<SPIRVType *> &ArgTypes, 466 MachineIRBuilder &MIRBuilder); 467 468 SPIRVType * 469 getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder, 470 SPIRV::AccessQualifier::AccessQualifier AccQual); 471 472 SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType); 473 Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I, 474 SPIRVType *SpvType, 475 const SPIRVInstrInfo &TII, unsigned BitWidth, 476 bool ZeroAsNull); 477 Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I, 478 SPIRVType *SpvType, 479 const SPIRVInstrInfo &TII, Constant *CA, 480 unsigned BitWidth, unsigned ElemCnt, 481 bool ZeroAsNull = true); 482 483 Register getOrCreateIntCompositeOrNull(uint64_t Val, 484 MachineIRBuilder &MIRBuilder, 485 SPIRVType *SpvType, bool EmitIR, 486 Constant *CA, unsigned BitWidth, 487 unsigned ElemCnt); 488 489 // Returns a pointer to a SPIR-V pointer type with the given base type and 490 // storage class. It is the responsibility of the caller to make sure the 491 // decorations on the base type are valid for the given storage class. For 492 // example, it has the correct offset and stride decorations. 493 SPIRVType * 494 getOrCreateSPIRVPointerTypeInternal(SPIRVType *BaseType, 495 MachineIRBuilder &MIRBuilder, 496 SPIRV::StorageClass::StorageClass SC); 497 498 void addStructOffsetDecorations(Register Reg, StructType *Ty, 499 MachineIRBuilder &MIRBuilder); 500 void addArrayStrideDecorations(Register Reg, Type *ElementType, 501 MachineIRBuilder &MIRBuilder); 502 bool hasBlockDecoration(SPIRVType *Type) const; 503 504 SPIRVType * 505 getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, 506 SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed, 507 uint32_t Multisampled, uint32_t Sampled, 508 SPIRV::ImageFormat::ImageFormat ImageFormat, 509 SPIRV::AccessQualifier::AccessQualifier AccQual); 510 511 public: 512 Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, 513 SPIRVType *SpvType, bool EmitIR, 514 bool ZeroAsNull = true); 515 Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, 516 SPIRVType *SpvType, const SPIRVInstrInfo &TII, 517 bool ZeroAsNull = true); 518 Register createConstInt(const ConstantInt *CI, MachineInstr &I, 519 SPIRVType *SpvType, const SPIRVInstrInfo &TII, 520 bool ZeroAsNull); 521 Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, 522 const SPIRVInstrInfo &TII, 523 bool ZeroAsNull = true); 524 Register createConstFP(const ConstantFP *CF, MachineInstr &I, 525 SPIRVType *SpvType, const SPIRVInstrInfo &TII, 526 bool ZeroAsNull); 527 Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, 528 SPIRVType *SpvType = nullptr); 529 530 Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, 531 SPIRVType *SpvType, const SPIRVInstrInfo &TII, 532 bool ZeroAsNull = true); 533 Register getOrCreateConstVector(APFloat Val, MachineInstr &I, 534 SPIRVType *SpvType, const SPIRVInstrInfo &TII, 535 bool ZeroAsNull = true); 536 Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, 537 SPIRVType *SpvType, 538 const SPIRVInstrInfo &TII); 539 Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, 540 SPIRVType *SpvType, bool EmitIR); 541 Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, 542 SPIRVType *SpvType); 543 Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, 544 unsigned FilerMode, 545 MachineIRBuilder &MIRBuilder); 546 Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, 547 const SPIRVInstrInfo &TII); 548 Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, 549 StringRef Name, const GlobalValue *GV, 550 SPIRV::StorageClass::StorageClass Storage, 551 const MachineInstr *Init, bool IsConst, 552 bool HasLinkageTy, 553 SPIRV::LinkageType::LinkageType LinkageType, 554 MachineIRBuilder &MIRBuilder, 555 bool IsInstSelector); 556 Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, 557 uint32_t Set, uint32_t Binding, 558 StringRef Name, 559 MachineIRBuilder &MIRBuilder); 560 561 // Convenient helpers for getting types with check for duplicates. 562 SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, 563 MachineIRBuilder &MIRBuilder); 564 SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I, 565 const SPIRVInstrInfo &TII); 566 SPIRVType *getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I, 567 const SPIRVInstrInfo &TII, 568 unsigned SPIRVOPcode, Type *LLVMTy); 569 SPIRVType *getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, 570 const SPIRVInstrInfo &TII); 571 SPIRVType *getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, 572 bool EmitIR); 573 SPIRVType *getOrCreateSPIRVBoolType(MachineInstr &I, 574 const SPIRVInstrInfo &TII); 575 SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType, 576 unsigned NumElements, 577 MachineIRBuilder &MIRBuilder, 578 bool EmitIR); 579 SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType, 580 unsigned NumElements, MachineInstr &I, 581 const SPIRVInstrInfo &TII); 582 583 // Returns a pointer to a SPIR-V pointer type with the given base type and 584 // storage class. The base type will be translated to a SPIR-V type, and the 585 // appropriate layout decorations will be added to the base type. 586 SPIRVType *getOrCreateSPIRVPointerType(const Type *BaseType, 587 MachineIRBuilder &MIRBuilder, 588 SPIRV::StorageClass::StorageClass SC); 589 SPIRVType *getOrCreateSPIRVPointerType(const Type *BaseType, MachineInstr &I, 590 SPIRV::StorageClass::StorageClass SC); 591 592 // Returns a pointer to a SPIR-V pointer type with the given base type and 593 // storage class. It is the responsibility of the caller to make sure the 594 // decorations on the base type are valid for the given storage class. For 595 // example, it has the correct offset and stride decorations. 596 SPIRVType *getOrCreateSPIRVPointerType(SPIRVType *BaseType, 597 MachineIRBuilder &MIRBuilder, 598 SPIRV::StorageClass::StorageClass SC); 599 600 // Returns a pointer to a SPIR-V pointer type that is the same as `PtrType` 601 // except the stroage class has been changed to `SC`. It is the responsibility 602 // of the caller to be sure that the original and new storage class have the 603 // same layout requirements. 604 SPIRVType *changePointerStorageClass(SPIRVType *PtrType, 605 SPIRV::StorageClass::StorageClass SC, 606 MachineInstr &I); 607 608 SPIRVType *getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, 609 Type *ElemType, 610 SPIRV::StorageClass::StorageClass SC, 611 bool IsWritable, bool EmitIr = false); 612 613 SPIRVType *getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, 614 const TargetExtType *T, bool EmitIr = false); 615 616 SPIRVType * 617 getImageType(const TargetExtType *ExtensionType, 618 const SPIRV::AccessQualifier::AccessQualifier Qualifier, 619 MachineIRBuilder &MIRBuilder); 620 621 SPIRVType *getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder); 622 623 SPIRVType *getOrCreateOpTypeSampledImage(SPIRVType *ImageType, 624 MachineIRBuilder &MIRBuilder); 625 SPIRVType *getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, 626 const TargetExtType *ExtensionType, 627 const SPIRVType *ElemType, 628 uint32_t Scope, uint32_t Rows, 629 uint32_t Columns, uint32_t Use, 630 bool EmitIR); 631 SPIRVType * 632 getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, 633 SPIRV::AccessQualifier::AccessQualifier AccQual); 634 SPIRVType *getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder); 635 SPIRVType *getOrCreateOpTypeFunctionWithArgs( 636 const Type *Ty, SPIRVType *RetType, 637 const SmallVectorImpl<SPIRVType *> &ArgTypes, 638 MachineIRBuilder &MIRBuilder); 639 SPIRVType *getOrCreateOpTypeByOpcode(const Type *Ty, 640 MachineIRBuilder &MIRBuilder, 641 unsigned Opcode); 642 643 SPIRVType *getOrCreateUnknownType(const Type *Ty, 644 MachineIRBuilder &MIRBuilder, 645 unsigned Opcode, 646 const ArrayRef<MCOperand> Operands); 647 648 const TargetRegisterClass *getRegClass(SPIRVType *SpvType) const; 649 LLT getRegType(SPIRVType *SpvType) const; 650 651 MachineInstr *getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder, 652 const MDNode *AliasingListMD); 653 void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, 654 uint32_t Dec, const MDNode *GVarMD); 655 // Replace all uses of a |Old| with |New| updates the global registry type 656 // mappings. 657 void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld = true); 658 659 void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg); 660 void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg); 661 void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType); 662 }; 663 } // end namespace llvm 664 #endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H 665