[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / lib / Target / SPIRV / SPIRVDuplicatesTracker.h
blob96cc621791e972dddea8db1ba38d82ac3b785591
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.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
15 #define LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H
17 #include "MCTargetDesc/SPIRVBaseInfo.h"
18 #include "MCTargetDesc/SPIRVMCTargetDesc.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/MapVector.h"
21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
22 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include <type_traits>
26 namespace llvm {
27 namespace SPIRV {
28 // NOTE: using MapVector instead of DenseMap because it helps getting
29 // everything ordered in a stable manner for a price of extra (NumKeys)*PtrSize
30 // memory and expensive removals which do not happen anyway.
31 class DTSortableEntry : public MapVector<const MachineFunction *, Register> {
32 SmallVector<DTSortableEntry *, 2> Deps;
34 struct FlagsTy {
35 unsigned IsFunc : 1;
36 unsigned IsGV : 1;
37 // NOTE: bit-field default init is a C++20 feature.
38 FlagsTy() : IsFunc(0), IsGV(0) {}
40 FlagsTy Flags;
42 public:
43 // Common hoisting utility doesn't support function, because their hoisting
44 // require hoisting of params as well.
45 bool getIsFunc() const { return Flags.IsFunc; }
46 bool getIsGV() const { return Flags.IsGV; }
47 void setIsFunc(bool V) { Flags.IsFunc = V; }
48 void setIsGV(bool V) { Flags.IsGV = V; }
50 const SmallVector<DTSortableEntry *, 2> &getDeps() const { return Deps; }
51 void addDep(DTSortableEntry *E) { Deps.push_back(E); }
54 struct SpecialTypeDescriptor {
55 enum SpecialTypeKind {
56 STK_Empty = 0,
57 STK_Image,
58 STK_SampledImage,
59 STK_Sampler,
60 STK_Pipe,
61 STK_DeviceEvent,
62 STK_Pointer,
63 STK_Last = -1
65 SpecialTypeKind Kind;
67 unsigned Hash;
69 SpecialTypeDescriptor() = delete;
70 SpecialTypeDescriptor(SpecialTypeKind K) : Kind(K) { Hash = Kind; }
72 unsigned getHash() const { return Hash; }
74 virtual ~SpecialTypeDescriptor() {}
77 struct ImageTypeDescriptor : public SpecialTypeDescriptor {
78 union ImageAttrs {
79 struct BitFlags {
80 unsigned Dim : 3;
81 unsigned Depth : 2;
82 unsigned Arrayed : 1;
83 unsigned MS : 1;
84 unsigned Sampled : 2;
85 unsigned ImageFormat : 6;
86 unsigned AQ : 2;
87 } Flags;
88 unsigned Val;
91 ImageTypeDescriptor(const Type *SampledTy, unsigned Dim, unsigned Depth,
92 unsigned Arrayed, unsigned MS, unsigned Sampled,
93 unsigned ImageFormat, unsigned AQ = 0)
94 : SpecialTypeDescriptor(SpecialTypeKind::STK_Image) {
95 ImageAttrs Attrs;
96 Attrs.Val = 0;
97 Attrs.Flags.Dim = Dim;
98 Attrs.Flags.Depth = Depth;
99 Attrs.Flags.Arrayed = Arrayed;
100 Attrs.Flags.MS = MS;
101 Attrs.Flags.Sampled = Sampled;
102 Attrs.Flags.ImageFormat = ImageFormat;
103 Attrs.Flags.AQ = AQ;
104 Hash = (DenseMapInfo<Type *>().getHashValue(SampledTy) & 0xffff) ^
105 ((Attrs.Val << 8) | Kind);
108 static bool classof(const SpecialTypeDescriptor *TD) {
109 return TD->Kind == SpecialTypeKind::STK_Image;
113 struct SampledImageTypeDescriptor : public SpecialTypeDescriptor {
114 SampledImageTypeDescriptor(const Type *SampledTy, const MachineInstr *ImageTy)
115 : SpecialTypeDescriptor(SpecialTypeKind::STK_SampledImage) {
116 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
117 ImageTypeDescriptor TD(
118 SampledTy, ImageTy->getOperand(2).getImm(),
119 ImageTy->getOperand(3).getImm(), ImageTy->getOperand(4).getImm(),
120 ImageTy->getOperand(5).getImm(), ImageTy->getOperand(6).getImm(),
121 ImageTy->getOperand(7).getImm(), ImageTy->getOperand(8).getImm());
122 Hash = TD.getHash() ^ Kind;
125 static bool classof(const SpecialTypeDescriptor *TD) {
126 return TD->Kind == SpecialTypeKind::STK_SampledImage;
130 struct SamplerTypeDescriptor : public SpecialTypeDescriptor {
131 SamplerTypeDescriptor()
132 : SpecialTypeDescriptor(SpecialTypeKind::STK_Sampler) {
133 Hash = Kind;
136 static bool classof(const SpecialTypeDescriptor *TD) {
137 return TD->Kind == SpecialTypeKind::STK_Sampler;
141 struct PipeTypeDescriptor : public SpecialTypeDescriptor {
143 PipeTypeDescriptor(uint8_t AQ)
144 : SpecialTypeDescriptor(SpecialTypeKind::STK_Pipe) {
145 Hash = (AQ << 8) | Kind;
148 static bool classof(const SpecialTypeDescriptor *TD) {
149 return TD->Kind == SpecialTypeKind::STK_Pipe;
153 struct DeviceEventTypeDescriptor : public SpecialTypeDescriptor {
155 DeviceEventTypeDescriptor()
156 : SpecialTypeDescriptor(SpecialTypeKind::STK_DeviceEvent) {
157 Hash = Kind;
160 static bool classof(const SpecialTypeDescriptor *TD) {
161 return TD->Kind == SpecialTypeKind::STK_DeviceEvent;
165 struct PointerTypeDescriptor : public SpecialTypeDescriptor {
166 const Type *ElementType;
167 unsigned AddressSpace;
169 PointerTypeDescriptor() = delete;
170 PointerTypeDescriptor(const Type *ElementType, unsigned AddressSpace)
171 : SpecialTypeDescriptor(SpecialTypeKind::STK_Pointer),
172 ElementType(ElementType), AddressSpace(AddressSpace) {
173 Hash = (DenseMapInfo<Type *>().getHashValue(ElementType) & 0xffff) ^
174 ((AddressSpace << 8) | Kind);
177 static bool classof(const SpecialTypeDescriptor *TD) {
178 return TD->Kind == SpecialTypeKind::STK_Pointer;
181 } // namespace SPIRV
183 template <> struct DenseMapInfo<SPIRV::SpecialTypeDescriptor> {
184 static inline SPIRV::SpecialTypeDescriptor getEmptyKey() {
185 return SPIRV::SpecialTypeDescriptor(
186 SPIRV::SpecialTypeDescriptor::STK_Empty);
188 static inline SPIRV::SpecialTypeDescriptor getTombstoneKey() {
189 return SPIRV::SpecialTypeDescriptor(SPIRV::SpecialTypeDescriptor::STK_Last);
191 static unsigned getHashValue(SPIRV::SpecialTypeDescriptor Val) {
192 return Val.getHash();
194 static bool isEqual(SPIRV::SpecialTypeDescriptor LHS,
195 SPIRV::SpecialTypeDescriptor RHS) {
196 return getHashValue(LHS) == getHashValue(RHS);
200 template <typename KeyTy> class SPIRVDuplicatesTrackerBase {
201 public:
202 // NOTE: using MapVector instead of DenseMap helps getting everything ordered
203 // in a stable manner for a price of extra (NumKeys)*PtrSize memory and
204 // expensive removals which don't happen anyway.
205 using StorageTy = MapVector<KeyTy, SPIRV::DTSortableEntry>;
207 private:
208 StorageTy Storage;
210 public:
211 void add(KeyTy V, const MachineFunction *MF, Register R) {
212 if (find(V, MF).isValid())
213 return;
215 Storage[V][MF] = R;
216 if (std::is_same<Function,
217 typename std::remove_const<
218 typename std::remove_pointer<KeyTy>::type>::type>() ||
219 std::is_same<Argument,
220 typename std::remove_const<
221 typename std::remove_pointer<KeyTy>::type>::type>())
222 Storage[V].setIsFunc(true);
223 if (std::is_same<GlobalVariable,
224 typename std::remove_const<
225 typename std::remove_pointer<KeyTy>::type>::type>())
226 Storage[V].setIsGV(true);
229 Register find(KeyTy V, const MachineFunction *MF) const {
230 auto iter = Storage.find(V);
231 if (iter != Storage.end()) {
232 auto Map = iter->second;
233 auto iter2 = Map.find(MF);
234 if (iter2 != Map.end())
235 return iter2->second;
237 return Register();
240 const StorageTy &getAllUses() const { return Storage; }
242 private:
243 StorageTy &getAllUses() { return Storage; }
245 // The friend class needs to have access to the internal storage
246 // to be able to build dependency graph, can't declare only one
247 // function a 'friend' due to the incomplete declaration at this point
248 // and mutual dependency problems.
249 friend class SPIRVGeneralDuplicatesTracker;
252 template <typename T>
253 class SPIRVDuplicatesTracker : public SPIRVDuplicatesTrackerBase<const T *> {};
255 template <>
256 class SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor>
257 : public SPIRVDuplicatesTrackerBase<SPIRV::SpecialTypeDescriptor> {};
259 class SPIRVGeneralDuplicatesTracker {
260 SPIRVDuplicatesTracker<Type> TT;
261 SPIRVDuplicatesTracker<Constant> CT;
262 SPIRVDuplicatesTracker<GlobalVariable> GT;
263 SPIRVDuplicatesTracker<Function> FT;
264 SPIRVDuplicatesTracker<Argument> AT;
265 SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor> ST;
267 // NOTE: using MOs instead of regs to get rid of MF dependency to be able
268 // to use flat data structure.
269 // NOTE: replacing DenseMap with MapVector doesn't affect overall correctness
270 // but makes LITs more stable, should prefer DenseMap still due to
271 // significant perf difference.
272 using SPIRVReg2EntryTy =
273 MapVector<MachineOperand *, SPIRV::DTSortableEntry *>;
275 template <typename T>
276 void prebuildReg2Entry(SPIRVDuplicatesTracker<T> &DT,
277 SPIRVReg2EntryTy &Reg2Entry);
279 public:
280 void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
281 MachineModuleInfo *MMI);
283 void add(const Type *Ty, const MachineFunction *MF, Register R) {
284 TT.add(Ty, MF, R);
287 void add(const Type *PointerElementType, unsigned AddressSpace,
288 const MachineFunction *MF, Register R) {
289 ST.add(SPIRV::PointerTypeDescriptor(PointerElementType, AddressSpace), MF,
293 void add(const Constant *C, const MachineFunction *MF, Register R) {
294 CT.add(C, MF, R);
297 void add(const GlobalVariable *GV, const MachineFunction *MF, Register R) {
298 GT.add(GV, MF, R);
301 void add(const Function *F, const MachineFunction *MF, Register R) {
302 FT.add(F, MF, R);
305 void add(const Argument *Arg, const MachineFunction *MF, Register R) {
306 AT.add(Arg, MF, R);
309 void add(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF,
310 Register R) {
311 ST.add(TD, MF, R);
314 Register find(const Type *Ty, const MachineFunction *MF) {
315 return TT.find(const_cast<Type *>(Ty), MF);
318 Register find(const Type *PointerElementType, unsigned AddressSpace,
319 const MachineFunction *MF) {
320 return ST.find(
321 SPIRV::PointerTypeDescriptor(PointerElementType, AddressSpace), MF);
324 Register find(const Constant *C, const MachineFunction *MF) {
325 return CT.find(const_cast<Constant *>(C), MF);
328 Register find(const GlobalVariable *GV, const MachineFunction *MF) {
329 return GT.find(const_cast<GlobalVariable *>(GV), MF);
332 Register find(const Function *F, const MachineFunction *MF) {
333 return FT.find(const_cast<Function *>(F), MF);
336 Register find(const Argument *Arg, const MachineFunction *MF) {
337 return AT.find(const_cast<Argument *>(Arg), MF);
340 Register find(const SPIRV::SpecialTypeDescriptor &TD,
341 const MachineFunction *MF) {
342 return ST.find(TD, MF);
345 const SPIRVDuplicatesTracker<Type> *getTypes() { return &TT; }
347 } // namespace llvm
348 #endif // LLVM_LIB_TARGET_SPIRV_SPIRVDUPLICATESTRACKER_H