xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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