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