LLVM 20.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
63 STK_Last = -1
64};
65
66using SpecialTypeDescriptor = std::tuple<const Type *, unsigned, unsigned>;
67
69 struct BitFlags {
70 unsigned Dim : 3;
71 unsigned Depth : 2;
72 unsigned Arrayed : 1;
73 unsigned MS : 1;
74 unsigned Sampled : 2;
75 unsigned ImageFormat : 6;
76 unsigned AQ : 2;
78 unsigned Val;
79
80 ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,
81 unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {
82 Val = 0;
83 Flags.Dim = Dim;
85 Flags.Arrayed = Arrayed;
86 Flags.MS = MS;
87 Flags.Sampled = Sampled;
88 Flags.ImageFormat = ImageFormat;
89 Flags.AQ = AQ;
90 }
91};
92
94make_descr_image(const Type *SampledTy, unsigned Dim, unsigned Depth,
95 unsigned Arrayed, unsigned MS, unsigned Sampled,
96 unsigned ImageFormat, unsigned AQ = 0) {
97 return std::make_tuple(
98 SampledTy,
99 ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
101}
102
104make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy) {
105 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
106 return std::make_tuple(
107 SampledTy,
109 ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),
110 ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),
111 ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(),
112 ImageTy->getOperand(8).getImm())
113 .Val,
115}
116
118 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
119}
120
122 return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
123}
124
126 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
127}
128
130 unsigned AddressSpace) {
131 return std::make_tuple(ElementType, AddressSpace,
133}
134} // namespace SPIRV
135
136template <typename KeyTy> class SPIRVDuplicatesTrackerBase {
137public:
138 // NOTE: using MapVector instead of DenseMap helps getting everything ordered
139 // in a stable manner for a price of extra (NumKeys)*PtrSize memory and
140 // expensive removals which don't happen anyway.
142
143private:
144 StorageTy Storage;
145
146public:
147 void add(KeyTy V, const MachineFunction *MF, Register R) {
148 if (find(V, MF).isValid())
149 return;
150
151 Storage[V][MF] = R;
152 if (std::is_same<Function,
153 typename std::remove_const<
154 typename std::remove_pointer<KeyTy>::type>::type>() ||
155 std::is_same<Argument,
156 typename std::remove_const<
157 typename std::remove_pointer<KeyTy>::type>::type>())
158 Storage[V].setIsFunc(true);
159 if (std::is_same<GlobalVariable,
160 typename std::remove_const<
161 typename std::remove_pointer<KeyTy>::type>::type>())
162 Storage[V].setIsGV(true);
163 }
164
165 Register find(KeyTy V, const MachineFunction *MF) const {
166 auto iter = Storage.find(V);
167 if (iter != Storage.end()) {
168 auto Map = iter->second;
169 auto iter2 = Map.find(MF);
170 if (iter2 != Map.end())
171 return iter2->second;
172 }
173 return Register();
174 }
175
176 const StorageTy &getAllUses() const { return Storage; }
177
178private:
179 StorageTy &getAllUses() { return Storage; }
180
181 // The friend class needs to have access to the internal storage
182 // to be able to build dependency graph, can't declare only one
183 // function a 'friend' due to the incomplete declaration at this point
184 // and mutual dependency problems.
186};
187
188template <typename T>
190
191template <>
192class SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor>
193 : public SPIRVDuplicatesTrackerBase<SPIRV::SpecialTypeDescriptor> {};
194
203
204 // NOTE: using MOs instead of regs to get rid of MF dependency to be able
205 // to use flat data structure.
206 // NOTE: replacing DenseMap with MapVector doesn't affect overall correctness
207 // but makes LITs more stable, should prefer DenseMap still due to
208 // significant perf difference.
209 using SPIRVReg2EntryTy =
211
212 template <typename T>
213 void prebuildReg2Entry(SPIRVDuplicatesTracker<T> &DT,
214 SPIRVReg2EntryTy &Reg2Entry);
215
216public:
217 void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
218 MachineModuleInfo *MMI);
219
220 void add(const Type *Ty, const MachineFunction *MF, Register R) {
221 TT.add(unifyPtrType(Ty), MF, R);
222 }
223
224 void add(const Type *PointeeTy, unsigned AddressSpace,
225 const MachineFunction *MF, Register R) {
227 R);
228 }
229
230 void add(const Constant *C, const MachineFunction *MF, Register R) {
231 CT.add(C, MF, R);
232 }
233
234 void add(const GlobalVariable *GV, const MachineFunction *MF, Register R) {
235 GT.add(GV, MF, R);
236 }
237
238 void add(const Function *F, const MachineFunction *MF, Register R) {
239 FT.add(F, MF, R);
240 }
241
242 void add(const Argument *Arg, const MachineFunction *MF, Register R) {
243 AT.add(Arg, MF, R);
244 }
245
246 void add(const MachineInstr *MI, const MachineFunction *MF, Register R) {
247 MT.add(MI, MF, R);
248 }
249
251 Register R) {
252 ST.add(TD, MF, R);
253 }
254
255 Register find(const Type *Ty, const MachineFunction *MF) {
256 return TT.find(unifyPtrType(Ty), MF);
257 }
258
259 Register find(const Type *PointeeTy, unsigned AddressSpace,
260 const MachineFunction *MF) {
261 return ST.find(
263 }
264
266 return CT.find(const_cast<Constant *>(C), MF);
267 }
268
270 return GT.find(const_cast<GlobalVariable *>(GV), MF);
271 }
272
274 return FT.find(const_cast<Function *>(F), MF);
275 }
276
277 Register find(const Argument *Arg, const MachineFunction *MF) {
278 return AT.find(const_cast<Argument *>(Arg), MF);
279 }
280
282 return MT.find(const_cast<MachineInstr *>(MI), MF);
283 }
284
286 const MachineFunction *MF) {
287 return ST.find(TD, MF);
288 }
289
290 const SPIRVDuplicatesTracker<Type> *getTypes() { return &TT; }
291};
292} // namespace llvm
293#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())
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:42
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:569
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:579
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
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
SpecialTypeDescriptor make_descr_pipe(uint8_t AQ)
SpecialTypeDescriptor make_descr_sampler()
std::tuple< const Type *, unsigned, unsigned > SpecialTypeDescriptor
SpecialTypeDescriptor make_descr_event()
SpecialTypeDescriptor make_descr_image(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
SpecialTypeDescriptor make_descr_pointee(const Type *ElementType, unsigned AddressSpace)
SpecialTypeDescriptor make_descr_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
AddressSpace
Definition: NVPTXBaseInfo.h:21
const Type * unifyPtrType(const Type *Ty)
Definition: SPIRVUtils.h:235
struct llvm::SPIRV::ImageAttrs::BitFlags Flags
ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)