xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 "SPIRVDuplicatesTracker.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 
30 class SPIRVGlobalRegistry {
31   // Registers holding values which have types associated with them.
32   // Initialized upon VReg definition in IRTranslator.
33   // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
34   // where Reg = OpType...
35   // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not
36   // type-declaring ones).
37   DenseMap<const MachineFunction *, DenseMap<Register, SPIRVType *>>
38       VRegToTypeMap;
39 
40   // Map LLVM Type* to <MF, Reg>
41   SPIRVGeneralDuplicatesTracker DT;
42 
43   DenseMap<SPIRVType *, const Type *> SPIRVToLLVMType;
44 
45   // map a Function to its definition (as a machine instruction operand)
46   DenseMap<const Function *, const MachineOperand *> FunctionToInstr;
47   DenseMap<const MachineInstr *, const Function *> FunctionToInstrRev;
48   // map function pointer (as a machine instruction operand) to the used
49   // Function
50   DenseMap<const MachineOperand *, const Function *> InstrToFunction;
51   // Maps Functions to their calls (in a form of the machine instruction,
52   // OpFunctionCall) that happened before the definition is available
53   DenseMap<const Function *, SmallPtrSet<MachineInstr *, 8>> ForwardCalls;
54   // map a Function to its original return type before the clone function was
55   // created during substitution of aggregate arguments
56   // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`)
57   DenseMap<Value *, Type *> MutatedAggRet;
58 
59   // Look for an equivalent of the newType in the map. Return the equivalent
60   // if it's found, otherwise insert newType to the map and return the type.
61   const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
62                                         MachineIRBuilder &MIRBuilder);
63 
64   SmallPtrSet<const Type *, 4> TypesInProcessing;
65   DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;
66 
67   // if a function returns a pointer, this is to map it into TypedPointerType
68   DenseMap<const Function *, TypedPointerType *> FunResPointerTypes;
69 
70   // Number of bits pointers and size_t integers require.
71   const unsigned PointerSize;
72 
73   // Holds the maximum ID we have in the module.
74   unsigned Bound;
75 
76   // Maps values associated with untyped pointers into deduced element types of
77   // untyped pointers.
78   DenseMap<Value *, Type *> DeducedElTys;
79   // Maps composite values to deduced types where untyped pointers are replaced
80   // with typed ones.
81   DenseMap<Value *, Type *> DeducedNestedTys;
82   // Maps values to "assign type" calls, thus being a registry of created
83   // Intrinsic::spv_assign_ptr_type instructions.
84   DenseMap<Value *, CallInst *> AssignPtrTypeInstr;
85 
86   // Add a new OpTypeXXX instruction without checking for duplicates.
87   SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
88                              SPIRV::AccessQualifier::AccessQualifier AQ =
89                                  SPIRV::AccessQualifier::ReadWrite,
90                              bool EmitIR = true);
91   SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,
92                            SPIRV::AccessQualifier::AccessQualifier accessQual =
93                                SPIRV::AccessQualifier::ReadWrite,
94                            bool EmitIR = true);
95   SPIRVType *
96   restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
97                         SPIRV::AccessQualifier::AccessQualifier AccessQual,
98                         bool EmitIR);
99 
100 public:
101   SPIRVGlobalRegistry(unsigned PointerSize);
102 
103   MachineFunction *CurMF;
104 
add(const Constant * C,MachineFunction * MF,Register R)105   void add(const Constant *C, MachineFunction *MF, Register R) {
106     DT.add(C, MF, R);
107   }
108 
add(const GlobalVariable * GV,MachineFunction * MF,Register R)109   void add(const GlobalVariable *GV, MachineFunction *MF, Register R) {
110     DT.add(GV, MF, R);
111   }
112 
add(const Function * F,MachineFunction * MF,Register R)113   void add(const Function *F, MachineFunction *MF, Register R) {
114     DT.add(F, MF, R);
115   }
116 
add(const Argument * Arg,MachineFunction * MF,Register R)117   void add(const Argument *Arg, MachineFunction *MF, Register R) {
118     DT.add(Arg, MF, R);
119   }
120 
add(const MachineInstr * MI,MachineFunction * MF,Register R)121   void add(const MachineInstr *MI, MachineFunction *MF, Register R) {
122     DT.add(MI, MF, R);
123   }
124 
find(const MachineInstr * MI,MachineFunction * MF)125   Register find(const MachineInstr *MI, MachineFunction *MF) {
126     return DT.find(MI, MF);
127   }
128 
find(const Constant * C,MachineFunction * MF)129   Register find(const Constant *C, MachineFunction *MF) {
130     return DT.find(C, MF);
131   }
132 
find(const GlobalVariable * GV,MachineFunction * MF)133   Register find(const GlobalVariable *GV, MachineFunction *MF) {
134     return DT.find(GV, MF);
135   }
136 
find(const Function * F,MachineFunction * MF)137   Register find(const Function *F, MachineFunction *MF) {
138     return DT.find(F, MF);
139   }
140 
141   void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
142                       MachineModuleInfo *MMI = nullptr) {
143     DT.buildDepsGraph(Graph, MMI);
144   }
145 
setBound(unsigned V)146   void setBound(unsigned V) { Bound = V; }
getBound()147   unsigned getBound() { return Bound; }
148 
149   // Add a record to the map of function return pointer types.
addReturnType(const Function * ArgF,TypedPointerType * DerivedTy)150   void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) {
151     FunResPointerTypes[ArgF] = DerivedTy;
152   }
153   // Find a record in the map of function return pointer types.
findReturnType(const Function * ArgF)154   const TypedPointerType *findReturnType(const Function *ArgF) {
155     auto It = FunResPointerTypes.find(ArgF);
156     return It == FunResPointerTypes.end() ? nullptr : It->second;
157   }
158 
159   // A registry of "assign type" records:
160   // - Add a record.
addAssignPtrTypeInstr(Value * Val,CallInst * AssignPtrTyCI)161   void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) {
162     AssignPtrTypeInstr[Val] = AssignPtrTyCI;
163   }
164   // - Find a record.
findAssignPtrTypeInstr(const Value * Val)165   CallInst *findAssignPtrTypeInstr(const Value *Val) {
166     auto It = AssignPtrTypeInstr.find(Val);
167     return It == AssignPtrTypeInstr.end() ? nullptr : It->second;
168   }
169 
170   // A registry of mutated values
171   // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`):
172   // - Add a record.
addMutated(Value * Val,Type * Ty)173   void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; }
174   // - Find a record.
findMutated(const Value * Val)175   Type *findMutated(const Value *Val) {
176     auto It = MutatedAggRet.find(Val);
177     return It == MutatedAggRet.end() ? nullptr : It->second;
178   }
179 
180   // Deduced element types of untyped pointers and composites:
181   // - Add a record to the map of deduced element types.
addDeducedElementType(Value * Val,Type * Ty)182   void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }
183   // - Find a record in the map of deduced element types.
findDeducedElementType(const Value * Val)184   Type *findDeducedElementType(const Value *Val) {
185     auto It = DeducedElTys.find(Val);
186     return It == DeducedElTys.end() ? nullptr : It->second;
187   }
188   // - Add a record to the map of deduced composite types.
addDeducedCompositeType(Value * Val,Type * Ty)189   void addDeducedCompositeType(Value *Val, Type *Ty) {
190     DeducedNestedTys[Val] = Ty;
191   }
192   // - Find a record in the map of deduced composite types.
findDeducedCompositeType(const Value * Val)193   Type *findDeducedCompositeType(const Value *Val) {
194     auto It = DeducedNestedTys.find(Val);
195     return It == DeducedNestedTys.end() ? nullptr : It->second;
196   }
197   // - Find a type of the given Global value
getDeducedGlobalValueType(const GlobalValue * Global)198   Type *getDeducedGlobalValueType(const GlobalValue *Global) {
199     // we may know element type if it was deduced earlier
200     Type *ElementTy = findDeducedElementType(Global);
201     if (!ElementTy) {
202       // or we may know element type if it's associated with a composite
203       // value
204       if (Value *GlobalElem =
205               Global->getNumOperands() > 0 ? Global->getOperand(0) : nullptr)
206         ElementTy = findDeducedCompositeType(GlobalElem);
207     }
208     return ElementTy ? ElementTy : Global->getValueType();
209   }
210 
211   // Map a machine operand that represents a use of a function via function
212   // pointer to a machine operand that represents the function definition.
213   // Return either the register or invalid value, because we have no context for
214   // a good diagnostic message in case of unexpectedly missing references.
getFunctionDefinitionByUse(const MachineOperand * Use)215   const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) {
216     auto ResF = InstrToFunction.find(Use);
217     if (ResF == InstrToFunction.end())
218       return nullptr;
219     auto ResReg = FunctionToInstr.find(ResF->second);
220     return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;
221   }
222 
223   // Map a Function to a machine instruction that represents the function
224   // definition.
getFunctionDefinition(const Function * F)225   const MachineInstr *getFunctionDefinition(const Function *F) {
226     if (!F)
227       return nullptr;
228     auto MOIt = FunctionToInstr.find(F);
229     return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent();
230   }
231 
232   // Map a Function to a machine instruction that represents the function
233   // definition.
getFunctionByDefinition(const MachineInstr * MI)234   const Function *getFunctionByDefinition(const MachineInstr *MI) {
235     if (!MI)
236       return nullptr;
237     auto FIt = FunctionToInstrRev.find(MI);
238     return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second;
239   }
240 
241   // map function pointer (as a machine instruction operand) to the used
242   // Function
recordFunctionPointer(const MachineOperand * MO,const Function * F)243   void recordFunctionPointer(const MachineOperand *MO, const Function *F) {
244     InstrToFunction[MO] = F;
245   }
246 
247   // map a Function to its definition (as a machine instruction)
recordFunctionDefinition(const Function * F,const MachineOperand * MO)248   void recordFunctionDefinition(const Function *F, const MachineOperand *MO) {
249     FunctionToInstr[F] = MO;
250     FunctionToInstrRev[MO->getParent()] = F;
251   }
252 
253   // Return true if any OpConstantFunctionPointerINTEL were generated
hasConstFunPtr()254   bool hasConstFunPtr() { return !InstrToFunction.empty(); }
255 
256   // Add a record about forward function call.
addForwardCall(const Function * F,MachineInstr * MI)257   void addForwardCall(const Function *F, MachineInstr *MI) {
258     auto It = ForwardCalls.find(F);
259     if (It == ForwardCalls.end())
260       ForwardCalls[F] = {MI};
261     else
262       It->second.insert(MI);
263   }
264 
265   // Map a Function to the vector of machine instructions that represents
266   // forward function calls or to nullptr if not found.
getForwardCalls(const Function * F)267   SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) {
268     auto It = ForwardCalls.find(F);
269     return It == ForwardCalls.end() ? nullptr : &It->second;
270   }
271 
272   // Get or create a SPIR-V type corresponding the given LLVM IR type,
273   // and map it to the given VReg by creating an ASSIGN_TYPE instruction.
274   SPIRVType *assignTypeToVReg(const Type *Type, Register VReg,
275                               MachineIRBuilder &MIRBuilder,
276                               SPIRV::AccessQualifier::AccessQualifier AQ =
277                                   SPIRV::AccessQualifier::ReadWrite,
278                               bool EmitIR = true);
279   SPIRVType *assignIntTypeToVReg(unsigned BitWidth, Register VReg,
280                                  MachineInstr &I, const SPIRVInstrInfo &TII);
281   SPIRVType *assignFloatTypeToVReg(unsigned BitWidth, Register VReg,
282                                    MachineInstr &I, const SPIRVInstrInfo &TII);
283   SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements,
284                                   Register VReg, MachineInstr &I,
285                                   const SPIRVInstrInfo &TII);
286 
287   // In cases where the SPIR-V type is already known, this function can be
288   // used to map it to the given VReg via an ASSIGN_TYPE instruction.
289   void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg,
290                              MachineFunction &MF);
291 
292   // Either generate a new OpTypeXXX instruction or return an existing one
293   // corresponding to the given LLVM IR type.
294   // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)
295   // because this method may be called from InstructionSelector and we don't
296   // want to emit extra IR instructions there.
297   SPIRVType *getOrCreateSPIRVType(const Type *Type,
298                                   MachineIRBuilder &MIRBuilder,
299                                   SPIRV::AccessQualifier::AccessQualifier AQ =
300                                       SPIRV::AccessQualifier::ReadWrite,
301                                   bool EmitIR = true);
302 
getTypeForSPIRVType(const SPIRVType * Ty)303   const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {
304     auto Res = SPIRVToLLVMType.find(Ty);
305     assert(Res != SPIRVToLLVMType.end());
306     return Res->second;
307   }
308 
309   // Return a pointee's type, or nullptr otherwise.
310   SPIRVType *getPointeeType(SPIRVType *PtrType);
311   // Return a pointee's type op code, or 0 otherwise.
312   unsigned getPointeeTypeOp(Register PtrReg);
313 
314   // Either generate a new OpTypeXXX instruction or return an existing one
315   // corresponding to the given string containing the name of the builtin type.
316   // Return nullptr if unable to recognize SPIRV type name from `TypeStr`.
317   SPIRVType *getOrCreateSPIRVTypeByName(
318       StringRef TypeStr, MachineIRBuilder &MIRBuilder,
319       SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,
320       SPIRV::AccessQualifier::AccessQualifier AQ =
321           SPIRV::AccessQualifier::ReadWrite);
322 
323   // Return the SPIR-V type instruction corresponding to the given VReg, or
324   // nullptr if no such type instruction exists. The second argument MF
325   // allows to search for the association in a context of the machine functions
326   // than the current one, without switching between different "current" machine
327   // functions.
328   SPIRVType *getSPIRVTypeForVReg(Register VReg,
329                                  const MachineFunction *MF = nullptr) const;
330 
331   // Whether the given VReg has a SPIR-V type mapped to it yet.
hasSPIRVTypeForVReg(Register VReg)332   bool hasSPIRVTypeForVReg(Register VReg) const {
333     return getSPIRVTypeForVReg(VReg) != nullptr;
334   }
335 
336   // Return the VReg holding the result of the given OpTypeXXX instruction.
337   Register getSPIRVTypeID(const SPIRVType *SpirvType) const;
338 
339   // Return previous value of the current machine function
setCurrentFunc(MachineFunction & MF)340   MachineFunction *setCurrentFunc(MachineFunction &MF) {
341     MachineFunction *Ret = CurMF;
342     CurMF = &MF;
343     return Ret;
344   }
345 
346   // Return true if the type is an aggregate type.
isAggregateType(SPIRVType * Type)347   bool isAggregateType(SPIRVType *Type) const {
348     return Type && (Type->getOpcode() == SPIRV::OpTypeStruct &&
349                     Type->getOpcode() == SPIRV::OpTypeArray);
350   }
351 
352   // Whether the given VReg has an OpTypeXXX instruction mapped to it with the
353   // given opcode (e.g. OpTypeFloat).
354   bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;
355 
356   // Return true if the given VReg's assigned SPIR-V type is either a scalar
357   // matching the given opcode, or a vector with an element type matching that
358   // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).
359   bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;
360 
361   // Return number of elements in a vector if the argument is associated with
362   // a vector type. Return 1 for a scalar type, and 0 for a missing type.
363   unsigned getScalarOrVectorComponentCount(Register VReg) const;
364   unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const;
365 
366   // For vectors or scalars of booleans, integers and floats, return the scalar
367   // type's bitwidth. Otherwise calls llvm_unreachable().
368   unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;
369 
370   // For vectors or scalars of integers and floats, return total bitwidth of the
371   // argument. Otherwise returns 0.
372   unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const;
373 
374   // Returns either pointer to integer type, that may be a type of vector
375   // elements or an original type, or nullptr if the argument is niether
376   // an integer scalar, nor an integer vector
377   const SPIRVType *retrieveScalarOrVectorIntType(const SPIRVType *Type) const;
378 
379   // For integer vectors or scalars, return whether the integers are signed.
380   bool isScalarOrVectorSigned(const SPIRVType *Type) const;
381 
382   // Gets the storage class of the pointer type assigned to this vreg.
383   SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;
384 
385   // Return the number of bits SPIR-V pointers and size_t variables require.
getPointerSize()386   unsigned getPointerSize() const { return PointerSize; }
387 
388   // Returns true if two types are defined and are compatible in a sense of
389   // OpBitcast instruction
390   bool isBitcastCompatible(const SPIRVType *Type1,
391                            const SPIRVType *Type2) const;
392 
393 private:
394   SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);
395 
396   const Type *adjustIntTypeByWidth(const Type *Ty) const;
397   unsigned adjustOpTypeIntWidth(unsigned Width) const;
398 
399   SPIRVType *getOpTypeInt(unsigned Width, MachineIRBuilder &MIRBuilder,
400                           bool IsSigned = false);
401 
402   SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);
403 
404   SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder);
405 
406   SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType,
407                              MachineIRBuilder &MIRBuilder);
408 
409   SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType,
410                             MachineIRBuilder &MIRBuilder, bool EmitIR = true);
411 
412   SPIRVType *getOpTypeOpaque(const StructType *Ty,
413                              MachineIRBuilder &MIRBuilder);
414 
415   SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,
416                              bool EmitIR = true);
417 
418   SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
419                               SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,
420                               Register Reg);
421 
422   SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,
423                                      MachineIRBuilder &MIRBuilder);
424 
425   SPIRVType *getOpTypeFunction(SPIRVType *RetType,
426                                const SmallVectorImpl<SPIRVType *> &ArgTypes,
427                                MachineIRBuilder &MIRBuilder);
428 
429   SPIRVType *
430   getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,
431                          SPIRV::AccessQualifier::AccessQualifier AccQual);
432 
433   std::tuple<Register, ConstantInt *, bool> getOrCreateConstIntReg(
434       uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
435       MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
436   std::tuple<Register, ConstantFP *, bool, unsigned> getOrCreateConstFloatReg(
437       APFloat Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
438       MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
439   SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);
440   Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I,
441                                    SPIRVType *SpvType,
442                                    const SPIRVInstrInfo &TII,
443                                    unsigned BitWidth);
444   Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I,
445                                       SPIRVType *SpvType,
446                                       const SPIRVInstrInfo &TII, Constant *CA,
447                                       unsigned BitWidth, unsigned ElemCnt,
448                                       bool ZeroAsNull = true);
449 
450   Register getOrCreateIntCompositeOrNull(uint64_t Val,
451                                          MachineIRBuilder &MIRBuilder,
452                                          SPIRVType *SpvType, bool EmitIR,
453                                          Constant *CA, unsigned BitWidth,
454                                          unsigned ElemCnt);
455 
456 public:
457   Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder,
458                             SPIRVType *SpvType = nullptr, bool EmitIR = true);
459   Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,
460                                SPIRVType *SpvType, const SPIRVInstrInfo &TII,
461                                bool ZeroAsNull = true);
462   Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType,
463                               const SPIRVInstrInfo &TII,
464                               bool ZeroAsNull = true);
465   Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder,
466                            SPIRVType *SpvType = nullptr);
467 
468   Register getOrCreateConstVector(uint64_t Val, MachineInstr &I,
469                                   SPIRVType *SpvType, const SPIRVInstrInfo &TII,
470                                   bool ZeroAsNull = true);
471   Register getOrCreateConstVector(APFloat Val, MachineInstr &I,
472                                   SPIRVType *SpvType, const SPIRVInstrInfo &TII,
473                                   bool ZeroAsNull = true);
474   Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I,
475                                     SPIRVType *SpvType,
476                                     const SPIRVInstrInfo &TII);
477   Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder,
478                                     SPIRVType *SpvType, bool EmitIR = true);
479   Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
480                                    SPIRVType *SpvType);
481   Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,
482                                 unsigned FilerMode,
483                                 MachineIRBuilder &MIRBuilder,
484                                 SPIRVType *SpvType);
485   Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType,
486                             const SPIRVInstrInfo &TII);
487   Register buildGlobalVariable(Register Reg, SPIRVType *BaseType,
488                                StringRef Name, const GlobalValue *GV,
489                                SPIRV::StorageClass::StorageClass Storage,
490                                const MachineInstr *Init, bool IsConst,
491                                bool HasLinkageTy,
492                                SPIRV::LinkageType::LinkageType LinkageType,
493                                MachineIRBuilder &MIRBuilder,
494                                bool IsInstSelector);
495 
496   // Convenient helpers for getting types with check for duplicates.
497   SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth,
498                                          MachineIRBuilder &MIRBuilder);
499   SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I,
500                                          const SPIRVInstrInfo &TII);
501   SPIRVType *getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I,
502                                   const SPIRVInstrInfo &TII,
503                                   unsigned SPIRVOPcode, Type *LLVMTy);
504   SPIRVType *getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I,
505                                        const SPIRVInstrInfo &TII);
506   SPIRVType *getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder);
507   SPIRVType *getOrCreateSPIRVBoolType(MachineInstr &I,
508                                       const SPIRVInstrInfo &TII);
509   SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,
510                                         unsigned NumElements,
511                                         MachineIRBuilder &MIRBuilder);
512   SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,
513                                         unsigned NumElements, MachineInstr &I,
514                                         const SPIRVInstrInfo &TII);
515   SPIRVType *getOrCreateSPIRVArrayType(SPIRVType *BaseType,
516                                        unsigned NumElements, MachineInstr &I,
517                                        const SPIRVInstrInfo &TII);
518 
519   SPIRVType *getOrCreateSPIRVPointerType(
520       SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
521       SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
522   SPIRVType *getOrCreateSPIRVPointerType(
523       SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &TII,
524       SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
525 
526   SPIRVType *
527   getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,
528                          SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,
529                          uint32_t Multisampled, uint32_t Sampled,
530                          SPIRV::ImageFormat::ImageFormat ImageFormat,
531                          SPIRV::AccessQualifier::AccessQualifier AccQual);
532 
533   SPIRVType *getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder);
534 
535   SPIRVType *getOrCreateOpTypeSampledImage(SPIRVType *ImageType,
536                                            MachineIRBuilder &MIRBuilder);
537   SPIRVType *getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder,
538                                        const TargetExtType *ExtensionType,
539                                        const SPIRVType *ElemType,
540                                        uint32_t Scope, uint32_t Rows,
541                                        uint32_t Columns, uint32_t Use);
542   SPIRVType *
543   getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder,
544                         SPIRV::AccessQualifier::AccessQualifier AccQual);
545   SPIRVType *getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder);
546   SPIRVType *getOrCreateOpTypeFunctionWithArgs(
547       const Type *Ty, SPIRVType *RetType,
548       const SmallVectorImpl<SPIRVType *> &ArgTypes,
549       MachineIRBuilder &MIRBuilder);
550   SPIRVType *getOrCreateOpTypeByOpcode(const Type *Ty,
551                                        MachineIRBuilder &MIRBuilder,
552                                        unsigned Opcode);
553 };
554 } // end namespace llvm
555 #endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H
556