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