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
26namespace llvm {
27class SPIRVSubtarget;
28using SPIRVType = const MachineInstr;
29using StructOffsetDecorator = std::function<void(Register)>;
30
31class SPIRVGlobalRegistry : public SPIRVIRMapping {
32 // Registers holding values which have types associated with them.
33 // Initialized upon VReg definition in IRTranslator.
34 // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
35 // where Reg = OpType...
36 // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. 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
110public:
111 SPIRVGlobalRegistry(unsigned PointerSize);
112
113 MachineFunction *CurMF;
114
115 void setBound(unsigned V) { Bound = V; }
116 unsigned getBound() { return Bound; }
117
118 void addGlobalObject(const Value *V, const MachineFunction *MF, Register R) {
119 Reg2GO[std::make_pair(x&: MF, y&: R)] = V;
120 }
121 const Value *getGlobalObject(const MachineFunction *MF, Register R) {
122 auto It = Reg2GO.find(Val: std::make_pair(x&: MF, y&: R));
123 return It == Reg2GO.end() ? nullptr : It->second;
124 }
125
126 // Add a record to the map of function return pointer types.
127 void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) {
128 FunResPointerTypes[ArgF] = DerivedTy;
129 }
130 // Find a record in the map of function return pointer types.
131 const TypedPointerType *findReturnType(const Function *ArgF) {
132 auto It = FunResPointerTypes.find(Val: ArgF);
133 return It == FunResPointerTypes.end() ? nullptr : It->second;
134 }
135
136 // A registry of "assign type" records:
137 // - Add a record.
138 void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) {
139 AssignPtrTypeInstr[Val] = AssignPtrTyCI;
140 }
141 // - Find a record.
142 CallInst *findAssignPtrTypeInstr(const Value *Val) {
143 auto It = AssignPtrTypeInstr.find(Val);
144 return It == AssignPtrTypeInstr.end() ? nullptr : It->second;
145 }
146 // - Find a record and update its key or add a new record, if found.
147 void updateIfExistAssignPtrTypeInstr(Value *OldVal, Value *NewVal,
148 bool DeleteOld) {
149 if (CallInst *CI = findAssignPtrTypeInstr(Val: OldVal)) {
150 if (DeleteOld)
151 AssignPtrTypeInstr.erase(Val: OldVal);
152 AssignPtrTypeInstr[NewVal] = CI;
153 }
154 }
155
156 // A registry of mutated values
157 // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`):
158 // - Add a record.
159 void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; }
160 // - Find a record.
161 Type *findMutated(const Value *Val) {
162 auto It = MutatedAggRet.find(Val);
163 return It == MutatedAggRet.end() ? nullptr : It->second;
164 }
165
166 // A registry of value's attributes (type, name)
167 // - Add a record.
168 void addValueAttrs(MachineInstr *Key, std::pair<Type *, std::string> Val) {
169 ValueAttrs[Key] = Val;
170 }
171 // - Find a record.
172 bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name) {
173 auto It = ValueAttrs.find(Val: Key);
174 if (It == ValueAttrs.end())
175 return false;
176 Ty = It->second.first;
177 Name = It->second.second;
178 return true;
179 }
180
181 // Deduced element types of untyped pointers and composites:
182 // - Add a record to the map of deduced element types.
183 void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }
184 // - Find a record in the map of deduced element types.
185 Type *findDeducedElementType(const Value *Val) {
186 auto It = DeducedElTys.find(Val);
187 return It == DeducedElTys.end() ? nullptr : It->second;
188 }
189 // - Find a record and update its key or add a new record, if found.
190 void updateIfExistDeducedElementType(Value *OldVal, Value *NewVal,
191 bool DeleteOld) {
192 if (Type *Ty = findDeducedElementType(Val: OldVal)) {
193 if (DeleteOld)
194 DeducedElTys.erase(Val: OldVal);
195 DeducedElTys[NewVal] = Ty;
196 }
197 }
198 // - Add a record to the map of deduced composite types.
199 void addDeducedCompositeType(Value *Val, Type *Ty) {
200 DeducedNestedTys[Val] = Ty;
201 }
202 // - Find a record in the map of deduced composite types.
203 Type *findDeducedCompositeType(const Value *Val) {
204 auto It = DeducedNestedTys.find(Val);
205 return It == DeducedNestedTys.end() ? nullptr : It->second;
206 }
207 // - Find a type of the given Global value
208 Type *getDeducedGlobalValueType(const GlobalValue *Global) {
209 // we may know element type if it was deduced earlier
210 Type *ElementTy = findDeducedElementType(Val: 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(i: 0) : nullptr)
216 ElementTy = findDeducedCompositeType(Val: 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.
225 const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) {
226 auto ResF = InstrToFunction.find(Val: Use);
227 if (ResF == InstrToFunction.end())
228 return nullptr;
229 auto ResReg = FunctionToInstr.find(Val: 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.
235 const MachineInstr *getFunctionDefinition(const Function *F) {
236 if (!F)
237 return nullptr;
238 auto MOIt = FunctionToInstr.find(Val: 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.
244 const Function *getFunctionByDefinition(const MachineInstr *MI) {
245 if (!MI)
246 return nullptr;
247 auto FIt = FunctionToInstrRev.find(Val: 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
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)
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
264 bool hasConstFunPtr() { return !InstrToFunction.empty(); }
265
266 // Add a record about forward function call.
267 void addForwardCall(const Function *F, MachineInstr *MI) {
268 ForwardCalls[F].insert(Ptr: 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.
273 SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) {
274 auto It = ForwardCalls.find(Val: 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.
302 SPIRVType *getOrCreateSPIRVType(const Type *Type, MachineInstr &I,
303 SPIRV::AccessQualifier::AccessQualifier AQ,
304 bool EmitIR) {
305 MachineIRBuilder MIRBuilder(I);
306 return getOrCreateSPIRVType(Type, MIRBuilder, AQ, EmitIR);
307 }
308
309 SPIRVType *getOrCreateSPIRVType(const Type *Type,
310 MachineIRBuilder &MIRBuilder,
311 SPIRV::AccessQualifier::AccessQualifier AQ,
312 bool EmitIR) {
313 return getOrCreateSPIRVType(Type, MIRBuilder, AQ, ExplicitLayoutRequired: false, EmitIR);
314 }
315
316 const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {
317 auto Res = SPIRVToLLVMType.find(Val: 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.
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
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.
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.
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
425private:
426 SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);
427
428 const Type *adjustIntTypeByWidth(const Type *Ty) const;
429 unsigned adjustOpTypeIntWidth(unsigned Width) const;
430
431 SPIRVType *getOrCreateSPIRVType(const Type *Type,
432 MachineIRBuilder &MIRBuilder,
433 SPIRV::AccessQualifier::AccessQualifier AQ,
434 bool ExplicitLayoutRequired, bool EmitIR);
435
436 SPIRVType *getOpTypeInt(unsigned Width, MachineIRBuilder &MIRBuilder,
437 bool IsSigned = false);
438
439 SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);
440
441 SPIRVType *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
511public:
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