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
38
40
41 // map a Function to its definition (as a machine instruction operand)
43 // map function pointer (as a machine instruction operand) to the used
44 // Function
46
47 // Look for an equivalent of the newType in the map. Return the equivalent
48 // if it's found, otherwise insert newType to the map and return the type.
49 const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
50 MachineIRBuilder &MIRBuilder);
51
52 SmallPtrSet<const Type *, 4> TypesInProcessing;
53 DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;
54
55 // Number of bits pointers and size_t integers require.
56 const unsigned PointerSize;
57
58 // Add a new OpTypeXXX instruction without checking for duplicates.
59 SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
60 SPIRV::AccessQualifier::AccessQualifier AQ =
61 SPIRV::AccessQualifier::ReadWrite,
62 bool EmitIR = true);
63 SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,
64 SPIRV::AccessQualifier::AccessQualifier accessQual =
65 SPIRV::AccessQualifier::ReadWrite,
66 bool EmitIR = true);
67 SPIRVType *
68 restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
69 SPIRV::AccessQualifier::AccessQualifier AccessQual,
70 bool EmitIR);
71
72public:
73 SPIRVGlobalRegistry(unsigned PointerSize);
74
76
77 void add(const Constant *C, MachineFunction *MF, Register R) {
78 DT.add(C, MF, R);
79 }
80
81 void add(const GlobalVariable *GV, MachineFunction *MF, Register R) {
82 DT.add(GV, MF, R);
83 }
84
85 void add(const Function *F, MachineFunction *MF, Register R) {
86 DT.add(F, MF, R);
87 }
88
89 void add(const Argument *Arg, MachineFunction *MF, Register R) {
90 DT.add(Arg, MF, R);
91 }
92
94 return DT.find(C, MF);
95 }
96
98 return DT.find(GV, MF);
99 }
100
102 return DT.find(F, MF);
103 }
104
105 void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
106 MachineModuleInfo *MMI = nullptr) {
107 DT.buildDepsGraph(Graph, MMI);
108 }
109
110 // Map a machine operand that represents a use of a function via function
111 // pointer to a machine operand that represents the function definition.
112 // Return either the register or invalid value, because we have no context for
113 // a good diagnostic message in case of unexpectedly missing references.
115 auto ResF = InstrToFunction.find(Use);
116 if (ResF == InstrToFunction.end())
117 return nullptr;
118 auto ResReg = FunctionToInstr.find(ResF->second);
119 return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;
120 }
121 // map function pointer (as a machine instruction operand) to the used
122 // Function
124 InstrToFunction[MO] = F;
125 }
126 // map a Function to its definition (as a machine instruction)
128 FunctionToInstr[F] = MO;
129 }
130 // Return true if any OpConstantFunctionPointerINTEL were generated
131 bool hasConstFunPtr() { return !InstrToFunction.empty(); }
132
133 // Get or create a SPIR-V type corresponding the given LLVM IR type,
134 // and map it to the given VReg by creating an ASSIGN_TYPE instruction.
136 MachineIRBuilder &MIRBuilder,
137 SPIRV::AccessQualifier::AccessQualifier AQ =
138 SPIRV::AccessQualifier::ReadWrite,
139 bool EmitIR = true);
142 SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements,
143 Register VReg, MachineInstr &I,
144 const SPIRVInstrInfo &TII);
145
146 // In cases where the SPIR-V type is already known, this function can be
147 // used to map it to the given VReg via an ASSIGN_TYPE instruction.
149 MachineFunction &MF);
150
151 // Either generate a new OpTypeXXX instruction or return an existing one
152 // corresponding to the given LLVM IR type.
153 // EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)
154 // because this method may be called from InstructionSelector and we don't
155 // want to emit extra IR instructions there.
157 MachineIRBuilder &MIRBuilder,
158 SPIRV::AccessQualifier::AccessQualifier AQ =
159 SPIRV::AccessQualifier::ReadWrite,
160 bool EmitIR = true);
161
162 const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {
163 auto Res = SPIRVToLLVMType.find(Ty);
164 assert(Res != SPIRVToLLVMType.end());
165 return Res->second;
166 }
167
168 // Either generate a new OpTypeXXX instruction or return an existing one
169 // corresponding to the given string containing the name of the builtin type.
170 // Return nullptr if unable to recognize SPIRV type name from `TypeStr`.
172 StringRef TypeStr, MachineIRBuilder &MIRBuilder,
173 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,
174 SPIRV::AccessQualifier::AccessQualifier AQ =
175 SPIRV::AccessQualifier::ReadWrite);
176
177 // Return the SPIR-V type instruction corresponding to the given VReg, or
178 // nullptr if no such type instruction exists.
180
181 // Whether the given VReg has a SPIR-V type mapped to it yet.
182 bool hasSPIRVTypeForVReg(Register VReg) const {
183 return getSPIRVTypeForVReg(VReg) != nullptr;
184 }
185
186 // Return the VReg holding the result of the given OpTypeXXX instruction.
187 Register getSPIRVTypeID(const SPIRVType *SpirvType) const;
188
190
191 // Whether the given VReg has an OpTypeXXX instruction mapped to it with the
192 // given opcode (e.g. OpTypeFloat).
193 bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;
194
195 // Return true if the given VReg's assigned SPIR-V type is either a scalar
196 // matching the given opcode, or a vector with an element type matching that
197 // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).
198 bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;
199
200 // For vectors or scalars of ints/floats, return the scalar type's bitwidth.
201 unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;
202
203 // For integer vectors or scalars, return whether the integers are signed.
204 bool isScalarOrVectorSigned(const SPIRVType *Type) const;
205
206 // Gets the storage class of the pointer type assigned to this vreg.
207 SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;
208
209 // Return the number of bits SPIR-V pointers and size_t variables require.
210 unsigned getPointerSize() const { return PointerSize; }
211
212private:
213 SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);
214
215 SPIRVType *getOpTypeInt(uint32_t Width, MachineIRBuilder &MIRBuilder,
216 bool IsSigned = false);
217
218 SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);
219
220 SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder);
221
222 SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType,
223 MachineIRBuilder &MIRBuilder);
224
225 SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType,
226 MachineIRBuilder &MIRBuilder, bool EmitIR = true);
227
228 SPIRVType *getOpTypeOpaque(const StructType *Ty,
229 MachineIRBuilder &MIRBuilder);
230
231 SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,
232 bool EmitIR = true);
233
234 SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
235 SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,
236 Register Reg);
237
238 SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,
239 MachineIRBuilder &MIRBuilder);
240
241 SPIRVType *getOpTypeFunction(SPIRVType *RetType,
242 const SmallVectorImpl<SPIRVType *> &ArgTypes,
243 MachineIRBuilder &MIRBuilder);
244
245 SPIRVType *
246 getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,
247 SPIRV::AccessQualifier::AccessQualifier AccQual);
248
249 std::tuple<Register, ConstantInt *, bool> getOrCreateConstIntReg(
250 uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,
251 MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);
252 SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);
253 Register getOrCreateIntCompositeOrNull(uint64_t Val, MachineInstr &I,
254 SPIRVType *SpvType,
255 const SPIRVInstrInfo &TII,
256 Constant *CA, unsigned BitWidth,
257 unsigned ElemCnt);
258 Register getOrCreateIntCompositeOrNull(uint64_t Val,
259 MachineIRBuilder &MIRBuilder,
260 SPIRVType *SpvType, bool EmitIR,
261 Constant *CA, unsigned BitWidth,
262 unsigned ElemCnt);
263
264public:
266 SPIRVType *SpvType = nullptr, bool EmitIR = true);
268 SPIRVType *SpvType, const SPIRVInstrInfo &TII);
270 SPIRVType *SpvType = nullptr);
272 SPIRVType *SpvType,
273 const SPIRVInstrInfo &TII);
275 SPIRVType *SpvType,
276 const SPIRVInstrInfo &TII);
278 SPIRVType *SpvType, bool EmitIR = true);
280 SPIRVType *SpvType, bool EmitIR = true);
282 SPIRVType *SpvType);
283 Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,
284 unsigned FilerMode,
285 MachineIRBuilder &MIRBuilder,
286 SPIRVType *SpvType);
288 const SPIRVInstrInfo &TII);
290 StringRef Name, const GlobalValue *GV,
291 SPIRV::StorageClass::StorageClass Storage,
292 const MachineInstr *Init, bool IsConst,
293 bool HasLinkageTy,
294 SPIRV::LinkageType::LinkageType LinkageType,
295 MachineIRBuilder &MIRBuilder,
296 bool IsInstSelector);
297
298 // Convenient helpers for getting types with check for duplicates.
300 MachineIRBuilder &MIRBuilder);
302 const SPIRVInstrInfo &TII);
305 const SPIRVInstrInfo &TII);
307 unsigned NumElements,
308 MachineIRBuilder &MIRBuilder);
310 unsigned NumElements, MachineInstr &I,
311 const SPIRVInstrInfo &TII);
313 unsigned NumElements, MachineInstr &I,
314 const SPIRVInstrInfo &TII);
315
317 SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,
318 SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
321 SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);
322
323 SPIRVType *
324 getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,
325 SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,
326 uint32_t Multisampled, uint32_t Sampled,
327 SPIRV::ImageFormat::ImageFormat ImageFormat,
328 SPIRV::AccessQualifier::AccessQualifier AccQual);
329
331
333 MachineIRBuilder &MIRBuilder);
334
335 SPIRVType *
337 SPIRV::AccessQualifier::AccessQualifier AccQual);
340 const Type *Ty, SPIRVType *RetType,
341 const SmallVectorImpl<SPIRVType *> &ArgTypes,
342 MachineIRBuilder &MIRBuilder);
344 MachineIRBuilder &MIRBuilder,
345 unsigned Opcode);
346};
347} // end namespace llvm
348#endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H
std::string Name
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)
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)
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)
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