LLVM 19.0.0git
SPIRVDuplicatesTracker.h
Go to the documentation of this file.
1//===-- SPIRVDuplicatesTracker.h - SPIR-V Duplicates Tracker ----*- 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// General infrastructure for keeping track of the values that according to
10// the SPIR-V binary layout should be global to the whole module.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
15#define LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
16
19#include "SPIRVUtils.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/MapVector.h"
24
25#include <type_traits>
26
27namespace llvm {
28namespace SPIRV {
29// NOTE: using MapVector instead of DenseMap because it helps getting
30// everything ordered in a stable manner for a price of extra (NumKeys)*PtrSize
31// memory and expensive removals which do not happen anyway.
32class DTSortableEntry : public MapVector<const MachineFunction *, Register> {
34
35 struct FlagsTy {
36 unsigned IsFunc : 1;
37 unsigned IsGV : 1;
38 // NOTE: bit-field default init is a C++20 feature.
39 FlagsTy() : IsFunc(0), IsGV(0) {}
40 };
41 FlagsTy Flags;
42
43public:
44 // Common hoisting utility doesn't support function, because their hoisting
45 // require hoisting of params as well.
46 bool getIsFunc() const { return Flags.IsFunc; }
47 bool getIsGV() const { return Flags.IsGV; }
48 void setIsFunc(bool V) { Flags.IsFunc = V; }
49 void setIsGV(bool V) { Flags.IsGV = V; }
50
51 const SmallVector<DTSortableEntry *, 2> &getDeps() const { return Deps; }
53};
54
64 STK_Last = -1
65 };
67
68 unsigned Hash;
69
72
73 unsigned getHash() const { return Hash; }
74
76};
77
79 union ImageAttrs {
80 struct BitFlags {
81 unsigned Dim : 3;
82 unsigned Depth : 2;
83 unsigned Arrayed : 1;
84 unsigned MS : 1;
85 unsigned Sampled : 2;
86 unsigned ImageFormat : 6;
87 unsigned AQ : 2;
89 unsigned Val;
90 };
91
92 ImageTypeDescriptor(const Type *SampledTy, unsigned Dim, unsigned Depth,
93 unsigned Arrayed, unsigned MS, unsigned Sampled,
94 unsigned ImageFormat, unsigned AQ = 0)
96 ImageAttrs Attrs;
97 Attrs.Val = 0;
98 Attrs.Flags.Dim = Dim;
99 Attrs.Flags.Depth = Depth;
100 Attrs.Flags.Arrayed = Arrayed;
101 Attrs.Flags.MS = MS;
102 Attrs.Flags.Sampled = Sampled;
103 Attrs.Flags.ImageFormat = ImageFormat;
104 Attrs.Flags.AQ = AQ;
105 Hash = (DenseMapInfo<Type *>().getHashValue(SampledTy) & 0xffff) ^
106 ((Attrs.Val << 8) | Kind);
107 }
108
109 static bool classof(const SpecialTypeDescriptor *TD) {
110 return TD->Kind == SpecialTypeKind::STK_Image;
111 }
112};
113
115 SampledImageTypeDescriptor(const Type *SampledTy, const MachineInstr *ImageTy)
117 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
119 SampledTy, ImageTy->getOperand(2).getImm(),
120 ImageTy->getOperand(3).getImm(), ImageTy->getOperand(4).getImm(),
121 ImageTy->getOperand(5).getImm(), ImageTy->getOperand(6).getImm(),
122 ImageTy->getOperand(7).getImm(), ImageTy->getOperand(8).getImm());
123 Hash = TD.getHash() ^ Kind;
124 }
125
126 static bool classof(const SpecialTypeDescriptor *TD) {
128 }
129};
130
134 Hash = Kind;
135 }
136
137 static bool classof(const SpecialTypeDescriptor *TD) {
139 }
140};
141
143
146 Hash = (AQ << 8) | Kind;
147 }
148
149 static bool classof(const SpecialTypeDescriptor *TD) {
150 return TD->Kind == SpecialTypeKind::STK_Pipe;
151 }
152};
153
155
158 Hash = Kind;
159 }
160
161 static bool classof(const SpecialTypeDescriptor *TD) {
163 }
164};
165
168 unsigned AddressSpace;
169
174 Hash = (DenseMapInfo<Type *>().getHashValue(ElementType) & 0xffff) ^
175 ((AddressSpace << 8) | Kind);
176 }
177
178 static bool classof(const SpecialTypeDescriptor *TD) {
180 }
181};
182} // namespace SPIRV
183
184template <> struct DenseMapInfo<SPIRV::SpecialTypeDescriptor> {
188 }
191 }
193 return Val.getHash();
194 }
197 return getHashValue(LHS) == getHashValue(RHS);
198 }
199};
200
201template <typename KeyTy> class SPIRVDuplicatesTrackerBase {
202public:
203 // NOTE: using MapVector instead of DenseMap helps getting everything ordered
204 // in a stable manner for a price of extra (NumKeys)*PtrSize memory and
205 // expensive removals which don't happen anyway.
207
208private:
209 StorageTy Storage;
210
211public:
212 void add(KeyTy V, const MachineFunction *MF, Register R) {
213 if (find(V, MF).isValid())
214 return;
215
216 Storage[V][MF] = R;
217 if (std::is_same<Function,
218 typename std::remove_const<
219 typename std::remove_pointer<KeyTy>::type>::type>() ||
220 std::is_same<Argument,
221 typename std::remove_const<
222 typename std::remove_pointer<KeyTy>::type>::type>())
223 Storage[V].setIsFunc(true);
224 if (std::is_same<GlobalVariable,
225 typename std::remove_const<
226 typename std::remove_pointer<KeyTy>::type>::type>())
227 Storage[V].setIsGV(true);
228 }
229
230 Register find(KeyTy V, const MachineFunction *MF) const {
231 auto iter = Storage.find(V);
232 if (iter != Storage.end()) {
233 auto Map = iter->second;
234 auto iter2 = Map.find(MF);
235 if (iter2 != Map.end())
236 return iter2->second;
237 }
238 return Register();
239 }
240
241 const StorageTy &getAllUses() const { return Storage; }
242
243private:
244 StorageTy &getAllUses() { return Storage; }
245
246 // The friend class needs to have access to the internal storage
247 // to be able to build dependency graph, can't declare only one
248 // function a 'friend' due to the incomplete declaration at this point
249 // and mutual dependency problems.
251};
252
253template <typename T>
255
256template <>
257class SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor>
258 : public SPIRVDuplicatesTrackerBase<SPIRV::SpecialTypeDescriptor> {};
259
268
269 // NOTE: using MOs instead of regs to get rid of MF dependency to be able
270 // to use flat data structure.
271 // NOTE: replacing DenseMap with MapVector doesn't affect overall correctness
272 // but makes LITs more stable, should prefer DenseMap still due to
273 // significant perf difference.
274 using SPIRVReg2EntryTy =
276
277 template <typename T>
278 void prebuildReg2Entry(SPIRVDuplicatesTracker<T> &DT,
279 SPIRVReg2EntryTy &Reg2Entry);
280
281public:
282 void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
283 MachineModuleInfo *MMI);
284
285 void add(const Type *Ty, const MachineFunction *MF, Register R) {
286 TT.add(Ty, MF, R);
287 }
288
289 void add(const Type *PointeeTy, unsigned AddressSpace,
290 const MachineFunction *MF, Register R) {
291 if (isUntypedPointerTy(PointeeTy))
292 PointeeTy =
294 getPointerAddressSpace(PointeeTy));
295 ST.add(SPIRV::PointerTypeDescriptor(PointeeTy, AddressSpace), MF, R);
296 }
297
298 void add(const Constant *C, const MachineFunction *MF, Register R) {
299 CT.add(C, MF, R);
300 }
301
302 void add(const GlobalVariable *GV, const MachineFunction *MF, Register R) {
303 GT.add(GV, MF, R);
304 }
305
306 void add(const Function *F, const MachineFunction *MF, Register R) {
307 FT.add(F, MF, R);
308 }
309
310 void add(const Argument *Arg, const MachineFunction *MF, Register R) {
311 AT.add(Arg, MF, R);
312 }
313
314 void add(const MachineInstr *MI, const MachineFunction *MF, Register R) {
315 MT.add(MI, MF, R);
316 }
317
319 Register R) {
320 ST.add(TD, MF, R);
321 }
322
323 Register find(const Type *Ty, const MachineFunction *MF) {
324 return TT.find(const_cast<Type *>(Ty), MF);
325 }
326
327 Register find(const Type *PointeeTy, unsigned AddressSpace,
328 const MachineFunction *MF) {
329 if (isUntypedPointerTy(PointeeTy))
330 PointeeTy =
332 getPointerAddressSpace(PointeeTy));
333 return ST.find(SPIRV::PointerTypeDescriptor(PointeeTy, AddressSpace), MF);
334 }
335
337 return CT.find(const_cast<Constant *>(C), MF);
338 }
339
341 return GT.find(const_cast<GlobalVariable *>(GV), MF);
342 }
343
345 return FT.find(const_cast<Function *>(F), MF);
346 }
347
348 Register find(const Argument *Arg, const MachineFunction *MF) {
349 return AT.find(const_cast<Argument *>(Arg), MF);
350 }
351
353 return MT.find(const_cast<MachineInstr *>(MI), MF);
354 }
355
357 const MachineFunction *MF) {
358 return ST.find(TD, MF);
359 }
360
361 const SPIRVDuplicatesTracker<Type> *getTypes() { return &TT; }
362};
363} // namespace llvm
364#endif // LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
This file declares the MachineIRBuilder class.
This file implements a map that provides insertion order iteration.
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
Value * LHS
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
This is an important base class in LLVM.
Definition: Constant.h:41
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:566
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:576
This class contains meta information specific to a module.
int64_t getImm() const
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
iterator end()
Definition: MapVector.h:71
iterator find(const KeyT &Key)
Definition: MapVector.h:167
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void add(KeyTy V, const MachineFunction *MF, Register R)
Register find(KeyTy V, const MachineFunction *MF) const
MapVector< KeyTy, SPIRV::DTSortableEntry > StorageTy
const StorageTy & getAllUses() const
void add(const GlobalVariable *GV, const MachineFunction *MF, Register R)
Register find(const Function *F, const MachineFunction *MF)
void add(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF, Register R)
void add(const Type *Ty, const MachineFunction *MF, Register R)
void add(const MachineInstr *MI, const MachineFunction *MF, Register R)
void add(const Function *F, const MachineFunction *MF, Register R)
Register find(const Type *Ty, const MachineFunction *MF)
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, MachineModuleInfo *MMI)
Register find(const Constant *C, const MachineFunction *MF)
Register find(const Argument *Arg, const MachineFunction *MF)
void add(const Argument *Arg, const MachineFunction *MF, Register R)
void add(const Type *PointeeTy, unsigned AddressSpace, const MachineFunction *MF, Register R)
Register find(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF)
Register find(const Type *PointeeTy, unsigned AddressSpace, const MachineFunction *MF)
void add(const Constant *C, const MachineFunction *MF, Register R)
const SPIRVDuplicatesTracker< Type > * getTypes()
Register find(const GlobalVariable *GV, const MachineFunction *MF)
Register find(const MachineInstr *MI, const MachineFunction *MF)
const SmallVector< DTSortableEntry *, 2 > & getDeps() const
void addDep(DTSortableEntry *E)
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:129
static IntegerType * getInt8Ty(LLVMContext &C)
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
@ 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
unsigned getPointerAddressSpace(const Type *T)
Definition: SPIRVUtils.h:126
AddressSpace
Definition: NVPTXBaseInfo.h:21
bool isUntypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:115
static SPIRV::SpecialTypeDescriptor getEmptyKey()
static SPIRV::SpecialTypeDescriptor getTombstoneKey()
static bool isEqual(SPIRV::SpecialTypeDescriptor LHS, SPIRV::SpecialTypeDescriptor RHS)
static unsigned getHashValue(SPIRV::SpecialTypeDescriptor Val)
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:50
static bool classof(const SpecialTypeDescriptor *TD)
ImageTypeDescriptor(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
static bool classof(const SpecialTypeDescriptor *TD)
static bool classof(const SpecialTypeDescriptor *TD)
PointerTypeDescriptor(const Type *ElementType, unsigned AddressSpace)
static bool classof(const SpecialTypeDescriptor *TD)
static bool classof(const SpecialTypeDescriptor *TD)
SampledImageTypeDescriptor(const Type *SampledTy, const MachineInstr *ImageTy)
static bool classof(const SpecialTypeDescriptor *TD)
struct llvm::SPIRV::ImageTypeDescriptor::ImageAttrs::BitFlags Flags