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_SPIRVGLOBALREGISTRY_H
17#define LLVM_LIB_TARGET_SPIRV_SPIRVGLOBALREGISTRY_H
18
19#include "MCTargetDesc/SPIRVBaseInfo.h"
20#include "SPIRVIRMapping.h"
21#include "SPIRVInstrInfo.h"
22#include "SPIRVTypeInst.h"
23#include "llvm/ADT/DenseSet.h"
24#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
25#include "llvm/IR/Constant.h"
26#include "llvm/IR/TypedPointerType.h"
27
28namespace llvm {
29class SPIRVSubtarget;
30
31using StructOffsetDecorator = std::function<void(Register)>;
32
33class SPIRVGlobalRegistry : public SPIRVIRMapping {
34 // Registers holding values which have types associated with them.
35 // Initialized upon VReg definition in IRTranslator.
36 // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
37 // where Reg = OpType...
38 // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not
39 // type-declaring ones).
40 DenseMap<const MachineFunction *, DenseMap<Register, SPIRVTypeInst>>
41 VRegToTypeMap;
42
43 DenseMap<SPIRVTypeInst, 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 SmallPtrSet<const Type *, 4> TypesInProcessing;
62 DenseMap<const Type *, SPIRVTypeInst> ForwardPointerTypes;
63
64 // Struct types decorated with Block, recorded at the point the decoration
65 // is emitted.
66 DenseSet<SPIRVTypeInst> BlockDecoratedTypes;
67
68 // Stores for each function the last inserted SPIR-V Type.
69 // See: SPIRVGlobalRegistry::createOpType.
70 DenseMap<const MachineFunction *, MachineInstr *> LastInsertedTypeMap;
71
72 // if a function returns a pointer, this is to map it into TypedPointerType
73 DenseMap<const Function *, TypedPointerType *> FunResPointerTypes;
74
75 // Current target's datalayout.
76 DataLayout DL;
77
78 // Holds the maximum ID we have in the module.
79 unsigned Bound;
80
81 // Maps values associated with untyped pointers into deduced element types of
82 // untyped pointers.
83 DenseMap<Value *, Type *> DeducedElTys;
84 // Maps composite values to deduced types where untyped pointers are replaced
85 // with typed ones.
86 DenseMap<Value *, Type *> DeducedNestedTys;
87
88 // Element type for each untyped-pointer register, which
89 // OpTypeUntypedPointerKHR omits but OpUntypedVariableKHR needs as a Data
90 // Type.
91 DenseMap<std::pair<const MachineFunction *, Register>, SPIRVTypeInst>
92 UntypedPointerElementTypes;
93 // Maps values to "assign type" calls, thus being a registry of created
94 // Intrinsic::spv_assign_ptr_type instructions.
95 DenseMap<Value *, CallInst *> AssignPtrTypeInstr;
96
97 // Maps OpVariable and OpFunction-related v-regs to its LLVM IR definition.
98 DenseMap<std::pair<const MachineFunction *, Register>, const Value *> Reg2GO;
99
100 // map of aliasing decorations to aliasing metadata
101 DenseMap<const MDNode *, MachineInstr *> AliasInstMDMap;
102
103 // Add a new OpTypeXXX instruction without checking for duplicates.
104 SPIRVTypeInst createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
105 SPIRV::AccessQualifier::AccessQualifier AQ,
106 bool ExplicitLayoutRequired, bool EmitIR);
107 SPIRVTypeInst
108 findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,
109 SPIRV::AccessQualifier::AccessQualifier accessQual,
110 bool ExplicitLayoutRequired, bool EmitIR);
111 SPIRVTypeInst
112 restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
113 SPIRV::AccessQualifier::AccessQualifier AccessQual,
114 bool ExplicitLayoutRequired, bool EmitIR);
115
116 // Internal function creating the Types/Constants at the correct position
117 // in the function by tweaking the passed "MIRBuilder" insertion point and
118 // restoring it to the correct position. "Op" should be the function creating
119 // the specific operation you need, and should return the newly created
120 // instruction.
121 const MachineInstr *createConstOrTypeAtFunctionEntry(
122 MachineIRBuilder &MIRBuilder,
123 std::function<MachineInstr *(MachineIRBuilder &)> Op);
124
125public:
126 SPIRVGlobalRegistry(DataLayout DL);
127
128 MachineFunction *CurMF;
129
130 void setBound(unsigned V) { Bound = V; }
131 unsigned getBound() { return Bound; }
132
133 void addGlobalObject(const Value *V, const MachineFunction *MF, Register R) {
134 Reg2GO[std::make_pair(x&: MF, y&: R)] = V;
135 }
136 const Value *getGlobalObject(const MachineFunction *MF, Register R) {
137 auto It = Reg2GO.find(Val: std::make_pair(x&: MF, y&: R));
138 return It == Reg2GO.end() ? nullptr : It->second;
139 }
140
141 // Add a record to the map of function return pointer types.
142 void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) {
143 FunResPointerTypes[ArgF] = DerivedTy;
144 }
145 // Find a record in the map of function return pointer types.
146 const TypedPointerType *findReturnType(const Function *ArgF) {
147 auto It = FunResPointerTypes.find(Val: ArgF);
148 return It == FunResPointerTypes.end() ? nullptr : It->second;
149 }
150
151 // A registry of "assign type" records:
152 // - Add a record.
153 void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) {
154 AssignPtrTypeInstr[Val] = AssignPtrTyCI;
155 }
156 // - Find a record.
157 CallInst *findAssignPtrTypeInstr(const Value *Val) {
158 auto It = AssignPtrTypeInstr.find(Val);
159 return It == AssignPtrTypeInstr.end() ? nullptr : It->second;
160 }
161 // - Find a record and update its key or add a new record, if found.
162 void updateIfExistAssignPtrTypeInstr(Value *OldVal, Value *NewVal,
163 bool DeleteOld) {
164 if (CallInst *CI = findAssignPtrTypeInstr(Val: OldVal)) {
165 if (DeleteOld)
166 AssignPtrTypeInstr.erase(Val: OldVal);
167 AssignPtrTypeInstr[NewVal] = CI;
168 }
169 }
170
171 // A registry of mutated values
172 // (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`):
173 // - Add a record.
174 void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; }
175 // - Find a record.
176 Type *findMutated(const Value *Val) {
177 auto It = MutatedAggRet.find(Val);
178 return It == MutatedAggRet.end() ? nullptr : It->second;
179 }
180
181 // A registry of value's attributes (type, name)
182 // - Add a record.
183 void addValueAttrs(MachineInstr *Key, std::pair<Type *, std::string> Val) {
184 ValueAttrs[Key] = Val;
185 }
186 // - Find a record.
187 bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name) {
188 auto It = ValueAttrs.find(Val: Key);
189 if (It == ValueAttrs.end())
190 return false;
191 Ty = It->second.first;
192 Name = It->second.second;
193 return true;
194 }
195
196 // Deduced element types of untyped pointers and composites:
197 // - Add a record to the map of deduced element types.
198 void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }
199 // - Find a record in the map of deduced element types.
200 Type *findDeducedElementType(const Value *Val) {
201 auto It = DeducedElTys.find(Val);
202 return It == DeducedElTys.end() ? nullptr : It->second;
203 }
204 // - Find a record and update its key or add a new record, if found.
205 void updateIfExistDeducedElementType(Value *OldVal, Value *NewVal,
206 bool DeleteOld) {
207 if (Type *Ty = findDeducedElementType(Val: OldVal)) {
208 if (DeleteOld)
209 DeducedElTys.erase(Val: OldVal);
210 DeducedElTys[NewVal] = Ty;
211 }
212 }
213 // - Add a record to the map of deduced composite types.
214 void addDeducedCompositeType(Value *Val, Type *Ty) {
215 DeducedNestedTys[Val] = Ty;
216 }
217 // - Find a record in the map of deduced composite types.
218 Type *findDeducedCompositeType(const Value *Val) {
219 auto It = DeducedNestedTys.find(Val);
220 return It == DeducedNestedTys.end() ? nullptr : It->second;
221 }
222
223 // Store the element type associated with an untyped-pointer register.
224 void setUntypedPtrElementType(Register Reg, SPIRVTypeInst ElemType) {
225 UntypedPointerElementTypes[{CurMF, Reg}] = ElemType;
226 }
227 // Get the element type associated with an untyped-pointer register.
228 SPIRVTypeInst getUntypedPtrElementType(Register Reg) const {
229 auto It = UntypedPointerElementTypes.find(Val: {CurMF, Reg});
230 return It == UntypedPointerElementTypes.end() ? nullptr : It->second;
231 }
232 // - Find a type of the given Global value
233 Type *getDeducedGlobalValueType(const GlobalValue *Global) {
234 // we may know element type if it was deduced earlier
235 Type *ElementTy = findDeducedElementType(Val: Global);
236 if (!ElementTy) {
237 // or we may know element type if it's associated with a composite
238 // value
239 if (Value *GlobalElem =
240 Global->getNumOperands() > 0 ? Global->getOperand(i: 0) : nullptr)
241 ElementTy = findDeducedCompositeType(Val: GlobalElem);
242 else if (const Function *Fn = dyn_cast<Function>(Val: Global))
243 ElementTy = SPIRV::getOriginalFunctionType(F: *Fn);
244 }
245 return ElementTy ? ElementTy : Global->getValueType();
246 }
247
248 // Map a machine operand that represents a use of a function via function
249 // pointer to a machine operand that represents the function definition.
250 // Return either the register or invalid value, because we have no context for
251 // a good diagnostic message in case of unexpectedly missing references.
252 const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) {
253 auto ResF = InstrToFunction.find(Val: Use);
254 if (ResF == InstrToFunction.end())
255 return nullptr;
256 auto ResReg = FunctionToInstr.find(Val: ResF->second);
257 return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;
258 }
259
260 // Map a Function to a machine instruction that represents the function
261 // definition.
262 const MachineInstr *getFunctionDefinition(const Function *F) {
263 if (!F)
264 return nullptr;
265 auto MOIt = FunctionToInstr.find(Val: F);
266 return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent();
267 }
268
269 // Map a Function to a machine instruction that represents the function
270 // definition.
271 const Function *getFunctionByDefinition(const MachineInstr *MI) {
272 if (!MI)
273 return nullptr;
274 auto FIt = FunctionToInstrRev.find(Val: MI);
275 return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second;
276 }
277
278 // map function pointer (as a machine instruction operand) to the used
279 // Function
280 void recordFunctionPointer(const MachineOperand *MO, const Function *F) {
281 InstrToFunction[MO] = F;
282 }
283
284 // map a Function to its definition (as a machine instruction)
285 void recordFunctionDefinition(const Function *F, const MachineOperand *MO) {
286 FunctionToInstr[F] = MO;
287 FunctionToInstrRev[MO->getParent()] = F;
288 }
289
290 // Return true if any OpConstantFunctionPointerINTEL were generated
291 bool hasConstFunPtr() { return !InstrToFunction.empty(); }
292
293 // Add a record about forward function call.
294 void addForwardCall(const Function *F, MachineInstr *MI) {
295 ForwardCalls[F].insert(Ptr: MI);
296 }
297
298 // Map a Function to the vector of machine instructions that represents
299 // forward function calls or to nullptr if not found.
300 SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) {
301 auto It = ForwardCalls.find(Val: F);
302 return It == ForwardCalls.end() ? nullptr : &It->second;
303 }
304
305 // Get or create a SPIR-V type corresponding the given LLVM IR type,
306 // and map it to the given VReg.
307 SPIRVTypeInst assignTypeToVReg(const Type *Type, Register VReg,
308 MachineIRBuilder &MIRBuilder,
309 SPIRV::AccessQualifier::AccessQualifier AQ,
310 bool EmitIR);
311 SPIRVTypeInst assignIntTypeToVReg(unsigned BitWidth, Register VReg,
312 MachineInstr &I, const SPIRVInstrInfo &TII);
313
314 // In cases where the SPIR-V type is already known, this function can be
315 // used to map it to the given VReg.
316 void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg,
317 const MachineFunction &MF);
318
319 // Either generate a new OpTypeXXX instruction or return an existing one
320 // corresponding to the given LLVM IR type.
321 // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)
322 // because this method may be called from InstructionSelector and we don't
323 // want to emit extra IR instructions there.
324 SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I,
325 SPIRV::AccessQualifier::AccessQualifier AQ,
326 bool EmitIR) {
327 MachineIRBuilder MIRBuilder(I);
328 return getOrCreateSPIRVType(Type, MIRBuilder, AQ, EmitIR);
329 }
330
331 SPIRVTypeInst getOrCreateSPIRVType(const Type *Type,
332 MachineIRBuilder &MIRBuilder,
333 SPIRV::AccessQualifier::AccessQualifier AQ,
334 bool EmitIR) {
335 return getOrCreateSPIRVType(Type, MIRBuilder, AQ, ExplicitLayoutRequired: false, EmitIR);
336 }
337
338 const Type *getTypeForSPIRVType(SPIRVTypeInst Ty) const {
339 auto Res = SPIRVToLLVMType.find(Val: Ty);
340 assert(Res != SPIRVToLLVMType.end());
341 return Res->second;
342 }
343
344 // Return a pointee's type, or nullptr otherwise.
345 SPIRVTypeInst getPointeeType(SPIRVTypeInst PtrType);
346
347 // Either generate a new OpTypeXXX instruction or return an existing one
348 // corresponding to the given string containing the name of the builtin type.
349 // Return nullptr if unable to recognize SPIRV type name from `TypeStr`.
350 SPIRVTypeInst getOrCreateSPIRVTypeByName(
351 StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR,
352 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,
353 SPIRV::AccessQualifier::AccessQualifier AQ =
354 SPIRV::AccessQualifier::ReadWrite);
355
356 // Return the SPIR-V type instruction corresponding to the given VReg, or
357 // nullptr if no such type instruction exists. The second argument MF
358 // allows to search for the association in a context of the machine functions
359 // than the current one, without switching between different "current" machine
360 // functions.
361 SPIRVTypeInst getSPIRVTypeForVReg(Register VReg,
362 const MachineFunction *MF = nullptr) const;
363
364 // Return the result type of the instruction defining the register.
365 SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF = nullptr);
366
367 // Return the VReg holding the result of the given OpTypeXXX instruction.
368 Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const;
369
370 // Return previous value of the current machine function
371 MachineFunction *setCurrentFunc(MachineFunction &MF) {
372 MachineFunction *Ret = CurMF;
373 CurMF = &MF;
374 return Ret;
375 }
376
377 // Return true if the type is an aggregate type.
378 bool isAggregateType(SPIRVTypeInst Type) const {
379 return Type && (Type->getOpcode() == SPIRV::OpTypeStruct ||
380 Type->getOpcode() == SPIRV::OpTypeArray);
381 }
382
383 // Whether the given VReg has an OpTypeXXX instruction mapped to it with the
384 // given opcode (e.g. OpTypeFloat).
385 bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;
386
387 // Return true if the given VReg's assigned SPIR-V type is either a scalar
388 // matching the given opcode, or a vector with an element type matching that
389 // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).
390 bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;
391
392 // Returns true if `Type` is a resource type. This could be an image type
393 // or a struct for a buffer decorated with the block decoration.
394 bool isResourceType(SPIRVTypeInst Type) const;
395
396 // Return number of elements in a vector if the argument is associated with
397 // a vector type. Return 1 for a scalar type, and 0 for a missing type.
398 unsigned getScalarOrVectorComponentCount(Register VReg) const;
399 unsigned getScalarOrVectorComponentCount(SPIRVTypeInst Type) const;
400
401 // Return the component type in a vector if the argument is associated with
402 // a vector type. Returns the argument itself for other types, and nullptr
403 // for a missing type.
404 SPIRVTypeInst getScalarOrVectorComponentType(SPIRVTypeInst Type) const;
405
406 // For vectors or scalars of booleans, integers and floats, return the scalar
407 // type's bitwidth. Otherwise calls llvm_unreachable().
408 unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const;
409
410 // For vectors or scalars of integers and floats, return total bitwidth of the
411 // argument. Otherwise returns 0.
412 unsigned getNumScalarOrVectorTotalBitWidth(SPIRVTypeInst Type) const;
413
414 // True if a pointer to this element type must stay typed rather than become
415 // OpTypeUntypedPointerKHR. Such an element type is either a function type,
416 // which an untyped pointer cannot express, or an opaque builtin type such as
417 // an image or a sampler.
418 bool shouldKeepTypedPtrType(SPIRVTypeInst ElemType) const;
419
420 // True if a pointer to this element type should be emitted as
421 // OpTypeUntypedPointerKHR rather than OpTypePointer.
422 bool shouldUseUntypedPointer(SPIRVTypeInst ElemType,
423 const SPIRVSubtarget &ST) const;
424
425 // Byte size of a pointer value's IR-deduced element type, or 0 if unknown.
426 // Array indexing and copy strides work in terms of the alloc size, so this
427 // reports the size a value of that type occupies in an array. For OpenCL
428 // that means a 3-component vector is as large as a 4-component one.
429 unsigned getDeducedPointeeByteSize(const Value *PtrVal) {
430 if (Type *ElemTy = findDeducedElementType(Val: PtrVal))
431 return DL.getTypeAllocSize(Ty: ElemTy).getFixedValue();
432 return 0;
433 }
434
435 // Returns either pointer to integer type, that may be a type of vector
436 // elements or an original type, or nullptr if the argument is niether
437 // an integer scalar, nor an integer vector
438 SPIRVTypeInst retrieveScalarOrVectorIntType(SPIRVTypeInst Type) const;
439
440 // For integer vectors or scalars, return whether the integers are signed.
441 bool isScalarOrVectorSigned(SPIRVTypeInst Type) const;
442
443 // Gets the storage class of the pointer type assigned to this vreg.
444 SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;
445 SPIRV::StorageClass::StorageClass
446 getPointerStorageClass(SPIRVTypeInst Type) const;
447
448 // Return the number of bits SPIR-V pointers and size_t variables require.
449 unsigned getPointerSize() const {
450 return DL.getPointerSizeInBits(/* AS = */ AS: 0);
451 }
452
453 // Returns true if two types are defined and are compatible in a sense of
454 // OpBitcast instruction
455 bool isBitcastCompatible(SPIRVTypeInst Type1, SPIRVTypeInst Type2) const;
456
457 // Informs about removal of the machine instruction and invalidates data
458 // structures referring this instruction.
459 void invalidateMachineInstr(MachineInstr *MI);
460
461private:
462 SPIRVTypeInst getOpTypeBool(MachineIRBuilder &MIRBuilder);
463
464 const Type *adjustIntTypeByWidth(const Type *Ty) const;
465 unsigned adjustOpTypeIntWidth(unsigned Width) const;
466
467 SPIRVTypeInst getOrCreateSPIRVType(const Type *Type,
468 MachineIRBuilder &MIRBuilder,
469 SPIRV::AccessQualifier::AccessQualifier AQ,
470 bool ExplicitLayoutRequired, bool EmitIR);
471
472 SPIRVTypeInst getOpTypeInt(unsigned Width, MachineIRBuilder &MIRBuilder,
473 bool IsSigned = false);
474
475 SPIRVTypeInst getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);
476
477 SPIRVTypeInst getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder,
478 SPIRV::FPEncoding::FPEncoding FPEncode);
479
480 SPIRVTypeInst getOpTypeVectorImpl(uint32_t NumElems, SPIRVTypeInst ElemType,
481 MachineIRBuilder &MIRBuilder,
482 bool IsLongVectorEXT = false);
483
484 SPIRVTypeInst getOpTypeVector(uint32_t NumElems, SPIRVTypeInst ElemType,
485 MachineIRBuilder &MIRBuilder);
486
487 SPIRVTypeInst getOpTypeVectorIdEXT(uint32_t NumElems, SPIRVTypeInst ElemType,
488 MachineIRBuilder &MIRBuilder);
489
490 SPIRVTypeInst getOpTypeArray(uint32_t NumElems, SPIRVTypeInst ElemType,
491 MachineIRBuilder &MIRBuilder,
492 bool ExplicitLayoutRequired, bool EmitIR);
493
494 SPIRVTypeInst getOpTypeOpaque(const StructType *Ty,
495 MachineIRBuilder &MIRBuilder);
496
497 SPIRVTypeInst getOpTypeStruct(const StructType *Ty,
498 MachineIRBuilder &MIRBuilder,
499 SPIRV::AccessQualifier::AccessQualifier AccQual,
500 StructOffsetDecorator Decorator, bool EmitIR);
501
502 SPIRVTypeInst getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
503 SPIRVTypeInst ElemType,
504 MachineIRBuilder &MIRBuilder, Register Reg);
505
506 SPIRVTypeInst
507 getOpTypeFunction(const FunctionType *Ty, SPIRVTypeInst RetType,
508 const SmallVectorImpl<SPIRVTypeInst> &ArgTypes,
509 MachineIRBuilder &MIRBuilder);
510
511 SPIRVTypeInst
512 getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,
513 SPIRV::AccessQualifier::AccessQualifier AccQual);
514
515 SPIRVTypeInst finishCreatingSPIRVType(const Type *LLVMTy,
516 SPIRVTypeInst SpirvType);
517 Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I,
518 SPIRVTypeInst SpvType,
519 const SPIRVInstrInfo &TII, unsigned BitWidth,
520 bool ZeroAsNull);
521 Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I,
522 SPIRVTypeInst SpvType,
523 const SPIRVInstrInfo &TII, Constant *CA,
524 unsigned BitWidth, unsigned ElemCnt,
525 bool ZeroAsNull = true);
526
527 Register getOrCreateIntCompositeOrNull(uint64_t Val,
528 MachineIRBuilder &MIRBuilder,
529 SPIRVTypeInst SpvType, bool EmitIR,
530 Constant *CA, unsigned BitWidth,
531 unsigned ElemCnt);
532
533 // Returns a pointer to a SPIR-V pointer type with the given base type and
534 // storage class. It is the responsibility of the caller to make sure the
535 // decorations on the base type are valid for the given storage class. For
536 // example, it has the correct offset and stride decorations.
537 // ForceTyped keeps an OpTypePointer even when untyped pointers are available,
538 // for cases where the pointee type must be preserved (e.g. a byval/byref/sret
539 // aggregate argument).
540 SPIRVTypeInst getOrCreateSPIRVPointerTypeInternal(
541 SPIRVTypeInst BaseType, MachineIRBuilder &MIRBuilder,
542 SPIRV::StorageClass::StorageClass SC, bool ForceTyped = false);
543
544 void addStructOffsetDecorations(Register Reg, StructType *Ty,
545 MachineIRBuilder &MIRBuilder);
546 void addArrayStrideDecorations(Register Reg, Type *ElementType,
547 MachineIRBuilder &MIRBuilder);
548
549 void constrainSelectedInstRegOperands(MachineInstrBuilder &MIB) const;
550
551 SPIRVTypeInst
552 getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder,
553 SPIRVTypeInst SampledType, SPIRV::Dim::Dim Dim,
554 uint32_t Depth, uint32_t Arrayed,
555 uint32_t Multisampled, uint32_t Sampled,
556 SPIRV::ImageFormat::ImageFormat ImageFormat,
557 SPIRV::AccessQualifier::AccessQualifier AccQual);
558
559public:
560 Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder,
561 SPIRVTypeInst SpvType, bool EmitIR,
562 bool ZeroAsNull = true);
563 Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,
564 SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII,
565 bool ZeroAsNull = true);
566 Register getOrCreateConstInt(const APInt &Val, MachineInstr &I,
567 SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII,
568 bool ZeroAsNull = true);
569 Register createConstInt(const ConstantInt *CI, MachineInstr &I,
570 SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII,
571 bool ZeroAsNull);
572 Register getOrCreateConstFP(APFloat Val, MachineInstr &I,
573 SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII,
574 bool ZeroAsNull = true);
575 Register createConstFP(const ConstantFP *CF, MachineInstr &I,
576 SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII,
577 bool ZeroAsNull);
578 Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder,
579 SPIRVTypeInst SpvType = nullptr);
580
581 Register getOrCreateConstVector(uint64_t Val, MachineInstr &I,
582 SPIRVTypeInst SpvType,
583 const SPIRVInstrInfo &TII,
584 bool ZeroAsNull = true);
585 Register getOrCreateConstVector(const APInt &Val, MachineInstr &I,
586 SPIRVTypeInst SpvType,
587 const SPIRVInstrInfo &TII,
588 bool ZeroAsNull = true);
589 Register getOrCreateConstVector(APFloat Val, MachineInstr &I,
590 SPIRVTypeInst SpvType,
591 const SPIRVInstrInfo &TII,
592 bool ZeroAsNull = true);
593 Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I,
594 SPIRVTypeInst SpvType,
595 const SPIRVInstrInfo &TII);
596 Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder,
597 SPIRVTypeInst SpvType, bool EmitIR);
598 Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,
599 SPIRVTypeInst SpvType);
600 Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,
601 unsigned FilerMode,
602 MachineIRBuilder &MIRBuilder);
603 Register getOrCreateUndef(MachineInstr &I, SPIRVTypeInst SpvType,
604 const SPIRVInstrInfo &TII);
605 Register buildGlobalVariable(
606 Register Reg, SPIRVTypeInst BaseType, StringRef Name,
607 const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage,
608 const MachineInstr *Init, bool IsConst,
609 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageType,
610 MachineIRBuilder &MIRBuilder, bool IsInstSelector);
611 Register getOrCreateGlobalVariableWithBinding(SPIRVTypeInst VarType,
612 uint32_t Set, uint32_t Binding,
613 StringRef Name,
614 MachineIRBuilder &MIRBuilder);
615
616 // Convenient helpers for getting types with check for duplicates.
617 SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth,
618 MachineIRBuilder &MIRBuilder);
619 SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I,
620 const SPIRVInstrInfo &TII);
621 SPIRVTypeInst getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I,
622 const SPIRVInstrInfo &TII,
623 unsigned SPIRVOPcode, Type *LLVMTy);
624 SPIRVTypeInst getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I,
625 const SPIRVInstrInfo &TII);
626 SPIRVTypeInst getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder,
627 bool EmitIR);
628 SPIRVTypeInst getOrCreateSPIRVBoolType(MachineInstr &I,
629 const SPIRVInstrInfo &TII);
630 SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType,
631 unsigned NumElements,
632 MachineIRBuilder &MIRBuilder,
633 bool EmitIR);
634 SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType,
635 unsigned NumElements,
636 MachineInstr &I,
637 const SPIRVInstrInfo &TII);
638 SPIRVTypeInst getOpTypeVoid(MachineIRBuilder &MIRBuilder);
639
640 // Returns a pointer to a SPIR-V pointer type with the given base type and
641 // storage class. The base type will be translated to a SPIR-V type, and the
642 // appropriate layout decorations will be added to the base type.
643 // See getOrCreateSPIRVPointerTypeInternal for ForceTyped.
644 SPIRVTypeInst getOrCreateSPIRVPointerType(
645 const Type *BaseType, MachineIRBuilder &MIRBuilder,
646 SPIRV::StorageClass::StorageClass SC, bool ForceTyped = false);
647 SPIRVTypeInst
648 getOrCreateSPIRVPointerType(const Type *BaseType, MachineInstr &I,
649 SPIRV::StorageClass::StorageClass SC,
650 bool ForceTyped = false);
651
652 // Like getOrCreateSPIRVPointerType, but always returns an OpTypePointer even
653 // when untyped pointers are available. Use this when the pointee type must be
654 // preserved (e.g. a byval/byref/sret aggregate argument).
655 SPIRVTypeInst
656 getOrCreateSPIRVTypedPointerType(const Type *BaseType,
657 MachineIRBuilder &MIRBuilder,
658 SPIRV::StorageClass::StorageClass SC) {
659 return getOrCreateSPIRVPointerType(BaseType, MIRBuilder, SC,
660 /*ForceTyped=*/ForceTyped: true);
661 }
662
663 // Returns a pointer to a SPIR-V pointer type with the given base type and
664 // storage class. It is the responsibility of the caller to make sure the
665 // decorations on the base type are valid for the given storage class. For
666 // example, it has the correct offset and stride decorations.
667 SPIRVTypeInst
668 getOrCreateSPIRVPointerType(SPIRVTypeInst BaseType,
669 MachineIRBuilder &MIRBuilder,
670 SPIRV::StorageClass::StorageClass SC);
671
672 // Returns a pointer to a SPIR-V pointer type that is the same as `PtrType`
673 // except the stroage class has been changed to `SC`. It is the responsibility
674 // of the caller to be sure that the original and new storage class have the
675 // same layout requirements.
676 SPIRVTypeInst changePointerStorageClass(SPIRVTypeInst PtrType,
677 SPIRV::StorageClass::StorageClass SC,
678 MachineInstr &I);
679
680 // Returns OpTypeUntypedPointerKHR for the given storage class.
681 SPIRVTypeInst
682 getOrCreateSPIRVUntypedPointerType(SPIRV::StorageClass::StorageClass SC,
683 MachineIRBuilder &MIRBuilder);
684
685 SPIRVTypeInst
686 getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType,
687 SPIRV::StorageClass::StorageClass SC,
688 bool IsWritable, bool EmitIr = false);
689
690 SPIRVTypeInst getOrCreatePaddingType(MachineIRBuilder &MIRBuilder);
691
692 SPIRVTypeInst getOrCreateVulkanPushConstantType(MachineIRBuilder &MIRBuilder,
693 Type *ElemType);
694
695 SPIRVTypeInst getOrCreateLayoutType(MachineIRBuilder &MIRBuilder,
696 const TargetExtType *T,
697 bool EmitIr = false);
698
699 SPIRVTypeInst
700 getImageType(const TargetExtType *ExtensionType,
701 const SPIRV::AccessQualifier::AccessQualifier Qualifier,
702 MachineIRBuilder &MIRBuilder);
703
704 SPIRVTypeInst getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder);
705
706 SPIRVTypeInst getOrCreateOpTypeSampledImage(SPIRVTypeInst ImageType,
707 MachineIRBuilder &MIRBuilder);
708 SPIRVTypeInst getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder,
709 const TargetExtType *ExtensionType,
710 SPIRVTypeInst ElemType,
711 uint32_t Scope, uint32_t Rows,
712 uint32_t Columns, uint32_t Use,
713 bool EmitIR);
714 SPIRVTypeInst
715 getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder,
716 SPIRV::AccessQualifier::AccessQualifier AccQual);
717 SPIRVTypeInst getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder);
718 SPIRVTypeInst getOrCreateOpTypeFunctionWithArgs(
719 const Type *Ty, SPIRVTypeInst RetType,
720 const SmallVectorImpl<SPIRVTypeInst> &ArgTypes,
721 MachineIRBuilder &MIRBuilder);
722 SPIRVTypeInst getOrCreateOpTypeByOpcode(const Type *Ty,
723 MachineIRBuilder &MIRBuilder,
724 unsigned Opcode);
725
726 SPIRVTypeInst getOrCreateUnknownType(const Type *Ty,
727 MachineIRBuilder &MIRBuilder,
728 unsigned Opcode,
729 const ArrayRef<MCOperand> Operands);
730
731 const TargetRegisterClass *getRegClass(SPIRVTypeInst SpvType) const;
732 LLT getRegType(SPIRVTypeInst SpvType) const;
733
734 MachineInstr *getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder,
735 const MDNode *AliasingListMD);
736 void buildMemAliasingOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder,
737 uint32_t Dec, const MDNode *GVarMD);
738 // Replace all uses of a |Old| with |New| updates the global registry type
739 // mappings.
740 void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld = true);
741
742 void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg,
743 bool CanUseAnyVectorRank);
744 void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg);
745 void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType);
746};
747} // end namespace llvm
748#endif // LLVM_LIB_TARGET_SPIRV_SPIRVGLOBALREGISTRY_H
749