LLVM 22.0.0git
SPIRVIRMapping.h
Go to the documentation of this file.
1//===------------ SPIRVMapping.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_SPIRVIRMAPPING_H
15#define LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H
16
19#include "SPIRVUtils.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/Hashing.h"
24
25namespace llvm {
26namespace SPIRV {
27
28inline size_t to_hash(const MachineInstr *MI) {
29 hash_code H = llvm::hash_combine(MI->getOpcode(), MI->getNumOperands());
30 for (unsigned I = MI->getNumDefs(); I < MI->getNumOperands(); ++I) {
31 const MachineOperand &MO = MI->getOperand(I);
33 H = llvm::hash_combine(H, MO.getType(), MO.getCImm());
35 H = llvm::hash_combine(H, MO.getType(), MO.getFPImm());
36 else
38 }
39 return H;
40}
41
42using MIHandle = std::tuple<const MachineInstr *, Register, size_t>;
43
45 return std::make_tuple(MI, MI->getOperand(0).getReg(), SPIRV::to_hash(MI));
46}
47
48using IRHandle = std::tuple<const void *, unsigned, unsigned>;
49using IRHandleMF = std::pair<IRHandle, const MachineFunction *>;
50
52 return std::make_pair(Handle, MF);
53}
54
71
73 struct BitFlags {
74 unsigned Dim : 3;
75 unsigned Depth : 2;
76 unsigned Arrayed : 1;
77 unsigned MS : 1;
78 unsigned Sampled : 2;
79 unsigned ImageFormat : 6;
80 unsigned AQ : 2;
81 } Flags;
82 unsigned Val;
83
84 ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,
85 unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {
86 Val = 0;
87 Flags.Dim = Dim;
88 Flags.Depth = Depth;
89 Flags.Arrayed = Arrayed;
90 Flags.MS = MS;
91 Flags.Sampled = Sampled;
92 Flags.ImageFormat = ImageFormat;
93 Flags.AQ = AQ;
94 }
95};
96
97inline IRHandle irhandle_image(const Type *SampledTy, unsigned Dim,
98 unsigned Depth, unsigned Arrayed, unsigned MS,
99 unsigned Sampled, unsigned ImageFormat,
100 unsigned AQ = 0) {
101 return std::make_tuple(
102 SampledTy,
103 ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
105}
106
107inline IRHandle irhandle_sampled_image(const Type *SampledTy,
108 const MachineInstr *ImageTy) {
109 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
110 unsigned AC = AccessQualifier::AccessQualifier::None;
111 if (ImageTy->getNumOperands() > 8)
112 AC = ImageTy->getOperand(8).getImm();
113 return std::make_tuple(
114 SampledTy,
116 ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),
117 ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),
118 ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(), AC)
119 .Val,
121}
122
124 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
125}
126
128 return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
129}
130
132 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
133}
134
135inline IRHandle irhandle_pointee(const Type *ElementType,
136 unsigned AddressSpace) {
137 return std::make_tuple(unifyPtrType(ElementType), AddressSpace,
139}
140
141inline IRHandle irhandle_ptr(const void *Ptr, unsigned Arg,
142 enum SpecialTypeKind STK) {
143 return std::make_tuple(Ptr, Arg, STK);
144}
145
146inline IRHandle irhandle_vkbuffer(const Type *ElementType,
147 StorageClass::StorageClass SC,
148 bool IsWriteable) {
149 return std::make_tuple(ElementType, (SC << 1) | IsWriteable,
151}
152
154 return std::make_tuple(nullptr, 0, SpecialTypeKind::STK_Padding);
155}
156
158 const Type *WrpTy = unifyPtrType(Ty);
159 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_ExplictLayoutType);
160}
161
162inline IRHandle handle(const Type *Ty) {
163 const Type *WrpTy = unifyPtrType(Ty);
164 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_Type);
165}
166
167inline IRHandle handle(const Value *V) {
168 return irhandle_ptr(V, V->getValueID(), STK_Value);
169}
170
171inline IRHandle handle(const MachineInstr *KeyMI) {
172 return irhandle_ptr(KeyMI, SPIRV::to_hash(KeyMI), STK_MachineInstr);
173}
174
175inline bool type_has_layout_decoration(const Type *T) {
176 return (isa<StructType>(T) || isa<ArrayType>(T));
177}
178
179} // namespace SPIRV
180
181// Bi-directional mappings between LLVM entities and (v-reg, machine function)
182// pairs support management of unique SPIR-V definitions per machine function
183// per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
187
188public:
189 bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
190 if (auto DefIt = Defs.find(MI); DefIt != Defs.end()) {
191 auto [ExistHandle, ExistMF] = DefIt->second;
192 if (Handle == ExistHandle && MI->getMF() == ExistMF)
193 return false; // already exists
194 // invalidate the record
195 Vregs.erase(DefIt->second);
196 Defs.erase(DefIt);
197 }
198 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MI->getMF());
200 auto It1 = Vregs.try_emplace(HandleMF, MIKey);
201 if (!It1.second) {
202 // there is an expired record that we need to invalidate
203 Defs.erase(std::get<0>(It1.first->second));
204 // update the record
205 It1.first->second = MIKey;
206 }
207 [[maybe_unused]] auto It2 = Defs.try_emplace(MI, HandleMF);
208 assert(It2.second);
209 return true;
210 }
211 bool erase(const MachineInstr *MI) {
212 bool Res = false;
213 if (auto It = Defs.find(MI); It != Defs.end()) {
214 Res = Vregs.erase(It->second);
215 Defs.erase(It);
216 }
217 return Res;
218 }
220 const MachineFunction *MF) {
221 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MF);
222 auto It = Vregs.find(HandleMF);
223 if (It == Vregs.end())
224 return nullptr;
225 auto [MI, Reg, Hash] = It->second;
226 const MachineInstr *Def = MF->getRegInfo().getVRegDef(Reg);
227 if (!Def || Def != MI || SPIRV::to_hash(MI) != Hash) {
228 // there is an expired record that we need to invalidate
229 erase(MI);
230 return nullptr;
231 }
232 assert(Defs.contains(MI) && Defs.find(MI)->second == HandleMF);
233 return MI;
234 }
236 const MachineInstr *MI = findMI(Handle, MF);
237 return MI ? MI->getOperand(0).getReg() : Register();
238 }
239
240 // helpers
241 bool add(const Type *PointeeTy, unsigned AddressSpace,
242 const MachineInstr *MI) {
243 return add(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MI);
244 }
245 Register find(const Type *PointeeTy, unsigned AddressSpace,
246 const MachineFunction *MF) {
247 return find(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
248 }
249 const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,
250 const MachineFunction *MF) {
251 return findMI(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
252 }
253
254 bool add(const Value *V, const MachineInstr *MI) {
255 return add(SPIRV::handle(V), MI);
256 }
257
258 bool add(const Type *T, bool RequiresExplicitLayout, const MachineInstr *MI) {
259 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T)) {
261 }
262 return add(SPIRV::handle(T), MI);
263 }
264
265 bool add(const MachineInstr *Obj, const MachineInstr *MI) {
266 return add(SPIRV::handle(Obj), MI);
267 }
268
269 Register find(const Value *V, const MachineFunction *MF) {
270 return find(SPIRV::handle(V), MF);
271 }
272
273 Register find(const Type *T, bool RequiresExplicitLayout,
274 const MachineFunction *MF) {
275 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
277 return find(SPIRV::handle(T), MF);
278 }
279
281 return find(SPIRV::handle(MI), MF);
282 }
283
284 const MachineInstr *findMI(const Value *Obj, const MachineFunction *MF) {
285 return findMI(SPIRV::handle(Obj), MF);
286 }
287
288 const MachineInstr *findMI(const Type *T, bool RequiresExplicitLayout,
289 const MachineFunction *MF) {
290 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
292 return findMI(SPIRV::handle(T), MF);
293 }
294
296 const MachineFunction *MF) {
297 return findMI(SPIRV::handle(Obj), MF);
298 }
299};
300} // namespace llvm
301#endif // LLVM_LIB_TARGET_SPIRV_SPIRVIRMAPPING_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the DenseMap class.
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
This file declares the MachineIRBuilder class.
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
int64_t getImm() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const ConstantFP * getFPImm() const
@ MO_CImmediate
Immediate >64bit operand.
@ MO_FPImmediate
Floating-point immediate operand.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
const MachineInstr * findMI(const Type *PointeeTy, unsigned AddressSpace, const MachineFunction *MF)
const MachineInstr * findMI(const Type *T, bool RequiresExplicitLayout, const MachineFunction *MF)
const MachineInstr * findMI(const MachineInstr *Obj, const MachineFunction *MF)
const MachineInstr * findMI(SPIRV::IRHandle Handle, const MachineFunction *MF)
bool add(const Value *V, const MachineInstr *MI)
Register find(const Value *V, const MachineFunction *MF)
Register find(const Type *T, bool RequiresExplicitLayout, const MachineFunction *MF)
bool add(const Type *PointeeTy, unsigned AddressSpace, const MachineInstr *MI)
bool erase(const MachineInstr *MI)
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
const MachineInstr * findMI(const Value *Obj, const MachineFunction *MF)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
Register find(const MachineInstr *MI, const MachineFunction *MF)
Register find(const Type *PointeeTy, unsigned AddressSpace, const MachineFunction *MF)
bool add(const MachineInstr *Obj, const MachineInstr *MI)
bool add(const Type *T, bool RequiresExplicitLayout, const MachineInstr *MI)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
TypeID getTypeID() const
Return the type id for the type.
Definition Type.h:136
LLVM Value Representation.
Definition Value.h:75
An opaque object representing a hash code.
Definition Hashing.h:76
IRHandle handle(const Type *Ty)
bool type_has_layout_decoration(const Type *T)
std::tuple< const MachineInstr *, Register, size_t > MIHandle
IRHandle irhandle_sampled_image(const Type *SampledTy, const MachineInstr *ImageTy)
std::tuple< const void *, unsigned, unsigned > IRHandle
size_t to_hash(const MachineInstr *MI)
IRHandle irhandle_pointee(const Type *ElementType, unsigned AddressSpace)
IRHandleMF getIRHandleMF(IRHandle Handle, const MachineFunction *MF)
IRHandle irhandle_padding()
IRHandle irhandle_vkbuffer(const Type *ElementType, StorageClass::StorageClass SC, bool IsWriteable)
IRHandle irhandle_sampler()
std::pair< IRHandle, const MachineFunction * > IRHandleMF
IRHandle irhandle_event()
MIHandle getMIKey(const MachineInstr *MI)
IRHandle irhandle_pipe(uint8_t AQ)
IRHandle irhandle_explict_layout_type(const Type *Ty)
IRHandle irhandle_ptr(const void *Ptr, unsigned Arg, enum SpecialTypeKind STK)
IRHandle irhandle_image(const Type *SampledTy, unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)
This is an optimization pass for GlobalISel generic memory operations.
const Type * unifyPtrType(const Type *Ty)
Definition SPIRVUtils.h:478
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:592
struct llvm::SPIRV::ImageAttrs::BitFlags Flags
ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)