LLVM 19.0.0git
SPIRVGlobalRegistry.h
Go to the documentation of this file.
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
21#include "SPIRVInstrInfo.h"
23
24namespace llvm {
25using SPIRVType = const MachineInstr;
26
28 // Registers holding values which have types associated with them.
29 // Initialized upon VReg definition in IRTranslator.
30 // Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>
31 // where Reg = OpType...
32 // while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not
33 // type-declaring ones).
35 VRegToTypeMap;
36
37 // Map LLVM Type* to <MF, Reg>
39
41
42 // map a Function to its definition (as a machine instruction operand)
44 // map function pointer (as a machine instruction operand) to the used
45 // Function
47
48 // Look for an equivalent of the newType in the map. Return the equivalent
49 // if it's found, otherwise insert newType to the map and return the type.
50 const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
51 MachineIRBuilder &MIRBuilder);
52
53 SmallPtrSet<const Type *, 4> TypesInProcessing;
54 DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;
55
56 // Number of bits pointers and size_t integers require.
57 const unsigned PointerSize;
58
59 // Add a new OpTypeXXX instruction without checking for duplicates.
60 SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
61 SPIRV::AccessQualifier::AccessQualifier AQ =
62 SPIRV::AccessQualifier::ReadWrite,
63 bool EmitIR = true);
64 SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,
65 SPIRV::AccessQualifier::AccessQualifier accessQual =
66 SPIRV::AccessQualifier::ReadWrite,
67 bool EmitIR = true);
68 SPIRVType *
69 restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
70 SPIRV::AccessQualifier::AccessQualifier AccessQual,
71 bool EmitIR);
72
73public:
74 SPIRVGlobalRegistry(unsigned PointerSize);
75
77
78 void add(const Constant *C, MachineFunction *MF, Register R) {
79 DT.add(C, MF, R);
80 }
81
82 void add(const GlobalVariable *GV, MachineFunction *MF, Register R) {
83 DT.add(GV, MF, R);
84 }
85
86 void add(const Function *F, MachineFunction *MF, Register R) {
87 DT.add(F, MF, R);
88 }
89
90 void add(const Argument *Arg, MachineFunction *MF, Register R) {
91 DT.add(Arg, MF, R);
92 }
93
95 return DT.find(C, MF);
96 }
97
99 return DT.find(GV, MF);
100 }
101
103 return DT.find(F, MF);
104 }
105
106 void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
107 MachineModuleInfo *MMI = nullptr) {
108 DT.buildDepsGraph(Graph, MMI);
109 }
110
111 // Map a machine operand that represents a use of a function via function
112 // pointer to a machine operand that represents the function definition.
113 // Return either the register or invalid value, because we have no context for
114 // a good diagnostic message in case of unexpectedly missing references.
116 auto ResF = InstrToFunction.find(Use);
117 if (ResF == InstrToFunction.end())
118 return nullptr;
119 auto ResReg = FunctionToInstr.find(ResF->second);
120 return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;
121 }
122 // map function pointer (as a machine instruction operand) to the used
123 // Function
125 InstrToFunction[MO] = F;
126 }
127 // map a Function to its definition (as a machine instruction)
129 FunctionToInstr[F] = MO;
130 }
131 // Return true if any OpConstantFunctionPointerINTEL were generated
132 bool hasConstFunPtr() { return !InstrToFunction.empty(); }
133
134 // Get or create a SPIR-V type corresponding the given LLVM IR type,
135 // and map it to the given VReg by creating an ASSIGN_TYPE instruction.
137 MachineIRBuilder &MIRBuilder,
138 SPIRV::AccessQualifier::AccessQualifier AQ =
139 SPIRV::AccessQualifier::ReadWrite,
140 bool EmitIR = true);
143 SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements,
144 Register VReg, MachineInstr &I,
145 const SPIRVInstrInfo &TII);
146
147 // In cases where the SPIR-V type is already known, this function can be
148 // used to map it to the given VReg via an ASSIGN_TYPE instruction.
150 MachineFunction &MF);
151
152 // Either generate a new OpTypeXXX instruction or return an existing one
153 // corresponding to the given LLVM IR type.
154 // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)
155 // because this method may be called from InstructionSelector and we don't
156 // want to emit extra IR instructions there.
158 MachineIRBuilder &MIRBuilder,
159 SPIRV::AccessQualifier::AccessQualifier AQ =
160 SPIRV::AccessQualifier::ReadWrite,
161 bool EmitIR = true);
162
163 const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {
164 auto Res = SPIRVToLLVMType.find(Ty);
165 assert(Res != SPIRVToLLVMType.end());
166 return Res->second;
167 }
168
169 // Either generate a new OpTypeXXX instruction or return an existing one
170 // corresponding to the given string containing the name of the builtin type.
171 // Return nullptr if unable to recognize SPIRV type name from `TypeStr`.
173 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
174 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,
175 SPIRV::AccessQualifier::AccessQualifier AQ =
176 SPIRV::AccessQualifier::ReadWrite);
177
178 // Return the SPIR-V type instruction corresponding to the given VReg, or
179 // nullptr if no such type instruction exists.
181
182 // Whether the given VReg has a SPIR-V type mapped to it yet.
183 bool hasSPIRVTypeForVReg(Register VReg) const {
184 return getSPIRVTypeForVReg(VReg) != nullptr;
185 }
186
187 // Return the VReg holding the result of the given OpTypeXXX instruction.
188 Register getSPIRVTypeID(const SPIRVType *SpirvType) const;
189
191
192 // Whether the given VReg has an OpTypeXXX instruction mapped to it with the
193 // given opcode (e.g. OpTypeFloat).
194 bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;
195
196 // Return true if the given VReg's assigned SPIR-V type is either a scalar
197 // matching the given opcode, or a vector with an element type matching that
198 // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).
199 bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;
200
201 // Return number of elements in a vector if the argument is associated with
202 // a vector type. Return 1 for a scalar type, and 0 for a missing type.
203 unsigned getScalarOrVectorComponentCount(Register VReg) const;
205
206 // For vectors or scalars of booleans, integers and floats, return the scalar
207 // type's bitwidth. Otherwise calls llvm_unreachable().
208 unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;
209
210 // For vectors or scalars of integers and floats, return total bitwidth of the
211 // argument. Otherwise returns 0.
212 unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const;
213
214 // Returns either pointer to integer type, that may be a type of vector
215 // elements or an original type, or nullptr if the argument is niether
216 // an integer scalar, nor an integer vector
218
219 // For integer vectors or scalars, return whether the integers are signed.
220 bool isScalarOrVectorSigned(const SPIRVType *Type) const;
221
222 // Gets the storage class of the pointer type assigned to this vreg.
223 SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;
224
225 // Return the number of bits SPIR-V pointers and size_t variables require.
226 unsigned getPointerSize() const { return PointerSize; }
227
228 // Returns true if two types are defined and are compatible in a sense of
229 // OpBitcast instruction
230 bool isBitcastCompatible(const SPIRVType *Type1,
231 const SPIRVType *Type2) const;
232
233private:
234 SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);
235
236 SPIRVType *getOpTypeInt(uint32_t Width, MachineIRBuilder &MIRBuilder,
237 bool IsSigned = false);
238
239 SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);
240
241 SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder);
242
243 SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType,
244 MachineIRBuilder &MIRBuilder);
245
246 SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType,
247 MachineIRBuilder &MIRBuilder, bool EmitIR = true);
248
249 SPIRVType *getOpTypeOpaque(const StructType *Ty,
250 MachineIRBuilder &MIRBuilder);
251
252 SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,
253 bool EmitIR = true);
254
255 SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
256 SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,
257 Register Reg);
258
259 SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,
260 MachineIRBuilder &MIRBuilder);
261
262 SPIRVType *getOpTypeFunction(SPIRVType *RetType,
263 const SmallVectorImpl<SPIRVType *> &ArgTypes,
264 MachineIRBuilder &MIRBuilder);
265
266 SPIRVType *
267 getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,
268 SPIRV::AccessQualifier::AccessQualifier AccQual);
269
270 std::tuple<Register, ConstantInt *, bool> getOrCreateConstIntReg(
271 uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
272 MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
273 SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);
274 Register getOrCreateIntCompositeOrNull(uint64_t Val, MachineInstr &I,
275 SPIRVType *SpvType,
276 const SPIRVInstrInfo &TII,
277 Constant *CA, unsigned BitWidth,
278 unsigned ElemCnt);
279 Register getOrCreateIntCompositeOrNull(uint64_t Val,
280 MachineIRBuilder &MIRBuilder,
281 SPIRVType *SpvType, bool EmitIR,
282 Constant *CA, unsigned BitWidth,
283 unsigned ElemCnt);
284
285public:
287 SPIRVType *SpvType = nullptr, bool EmitIR = true);
289 SPIRVType *SpvType, const SPIRVInstrInfo &TII);
291 SPIRVType *SpvType = nullptr);
293 SPIRVType *SpvType,
294 const SPIRVInstrInfo &TII);
296 SPIRVType *SpvType,
297 const SPIRVInstrInfo &TII);
299 SPIRVType *SpvType, bool EmitIR = true);
301 SPIRVType *SpvType, bool EmitIR = true);
303 SPIRVType *SpvType);
304 Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,
305 unsigned FilerMode,
306 MachineIRBuilder &MIRBuilder,
307 SPIRVType *SpvType);
309 const SPIRVInstrInfo &TII);
311 StringRef Name, const GlobalValue *GV,
312 SPIRV::StorageClass::StorageClass Storage,
313 const MachineInstr *Init, bool IsConst,
314 bool HasLinkageTy,
315 SPIRV::LinkageType::LinkageType LinkageType,
316 MachineIRBuilder &MIRBuilder,
317 bool IsInstSelector);
318
319 // Convenient helpers for getting types with check for duplicates.
321 MachineIRBuilder &MIRBuilder);
323 const SPIRVInstrInfo &TII);
326 const SPIRVInstrInfo &TII);
328 unsigned NumElements,
329 MachineIRBuilder &MIRBuilder);
331 unsigned NumElements, MachineInstr &I,
332 const SPIRVInstrInfo &TII);
334 unsigned NumElements, MachineInstr &I,
335 const SPIRVInstrInfo &TII);
336
338 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
339 SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
342 SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
343
344 SPIRVType *
345 getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,
346 SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,
347 uint32_t Multisampled, uint32_t Sampled,
348 SPIRV::ImageFormat::ImageFormat ImageFormat,
349 SPIRV::AccessQualifier::AccessQualifier AccQual);
350
352
354 MachineIRBuilder &MIRBuilder);
355
356 SPIRVType *
358 SPIRV::AccessQualifier::AccessQualifier AccQual);
361 const Type *Ty, SPIRVType *RetType,
362 const SmallVectorImpl<SPIRVType *> &ArgTypes,
363 MachineIRBuilder &MIRBuilder);
365 MachineIRBuilder &MIRBuilder,
366 unsigned Opcode);
367};
368} // end namespace llvm
369#endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H
std::string Name
ELFYAML::ELF_REL Type2
Definition: ELFYAML.cpp:1809
const HexagonInstrInfo * TII
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineIRBuilder class.
unsigned Reg
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents an incoming formal argument to a Function.
Definition: Argument.h:28
This is an important base class in LLVM.
Definition: Constant.h:41
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:155
bool empty() const
Definition: DenseMap.h:98
iterator end()
Definition: DenseMap.h:84
Helper class to build MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:69
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void add(const Type *Ty, const MachineFunction *MF, Register R)
Register find(const Type *Ty, const MachineFunction *MF)
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, MachineModuleInfo *MMI)
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
void recordFunctionDefinition(const Function *F, const MachineOperand *MO)
unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const
Register getOrCreateConsIntVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
void setCurrentFunc(MachineFunction &MF)
SPIRVType * assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
void add(const Constant *C, MachineFunction *MF, Register R)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled, SPIRV::ImageFormat::ImageFormat ImageFormat, SPIRV::AccessQualifier::AccessQualifier AccQual)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
SPIRVType * getSPIRVTypeForVReg(Register VReg) const
void add(const GlobalVariable *GV, MachineFunction *MF, Register R)
Register find(const Constant *C, MachineFunction *MF)
void add(const Argument *Arg, MachineFunction *MF, Register R)
const MachineOperand * getFunctionDefinitionByUse(const MachineOperand *Use)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, MachineFunction &MF)
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
Register find(const Function *F, MachineFunction *MF)
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, bool HasLinkageTy, SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
void add(const Function *F, MachineFunction *MF, Register R)
SPIRVType * assignIntTypeToVReg(unsigned BitWidth, Register VReg, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
Register find(const GlobalVariable *GV, MachineFunction *MF)
bool hasSPIRVTypeForVReg(Register VReg) const
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, MachineModuleInfo *MMI=nullptr)
SPIRVType * assignTypeToVReg(const Type *Type, Register VReg, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite, bool EmitIR=true)
SPIRVType * getOrCreateOpTypeFunctionWithArgs(const Type *Ty, SPIRVType *RetType, const SmallVectorImpl< SPIRVType * > &ArgTypes, MachineIRBuilder &MIRBuilder)
void recordFunctionPointer(const MachineOperand *MO, const Function *F)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVPointerType(SPIRVType *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SClass=SPIRV::StorageClass::Function)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register getOrCreateConsIntArray(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateSPIRVArrayType(SPIRVType *BaseType, unsigned NumElements, MachineInstr &I, const SPIRVInstrInfo &TII)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr, bool EmitIR=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:427
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Class to represent struct types.
Definition: DerivedTypes.h:216
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:191