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
25#include <type_traits>
26
27namespace llvm {
28namespace SPIRV {
29
30inline size_t to_hash(const MachineInstr *MI) {
31 hash_code H = llvm::hash_combine(MI->getOpcode(), MI->getNumOperands());
32 for (unsigned I = MI->getNumDefs(); I < MI->getNumOperands(); ++I) {
33 const MachineOperand &MO = MI->getOperand(I);
35 H = llvm::hash_combine(H, MO.getType(), MO.getCImm());
37 H = llvm::hash_combine(H, MO.getType(), MO.getFPImm());
38 else
40 }
41 return H;
42}
43
44using MIHandle = std::tuple<const MachineInstr *, Register, size_t>;
45
47 return std::make_tuple(MI, MI->getOperand(0).getReg(), SPIRV::to_hash(MI));
48}
49
50using IRHandle = std::tuple<const void *, unsigned, unsigned>;
51using IRHandleMF = std::pair<IRHandle, const MachineFunction *>;
52
54 return std::make_pair(Handle, MF);
55}
56
72
74 struct BitFlags {
75 unsigned Dim : 3;
76 unsigned Depth : 2;
77 unsigned Arrayed : 1;
78 unsigned MS : 1;
79 unsigned Sampled : 2;
80 unsigned ImageFormat : 6;
81 unsigned AQ : 2;
82 } Flags;
83 unsigned Val;
84
85 ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,
86 unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {
87 Val = 0;
88 Flags.Dim = Dim;
89 Flags.Depth = Depth;
90 Flags.Arrayed = Arrayed;
91 Flags.MS = MS;
92 Flags.Sampled = Sampled;
93 Flags.ImageFormat = ImageFormat;
94 Flags.AQ = AQ;
95 }
96};
97
98inline IRHandle irhandle_image(const Type *SampledTy, unsigned Dim,
99 unsigned Depth, unsigned Arrayed, unsigned MS,
100 unsigned Sampled, unsigned ImageFormat,
101 unsigned AQ = 0) {
102 return std::make_tuple(
103 SampledTy,
104 ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
106}
107
108inline IRHandle irhandle_sampled_image(const Type *SampledTy,
109 const MachineInstr *ImageTy) {
110 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
111 unsigned AC = AccessQualifier::AccessQualifier::None;
112 if (ImageTy->getNumOperands() > 8)
113 AC = ImageTy->getOperand(8).getImm();
114 return std::make_tuple(
115 SampledTy,
117 ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),
118 ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),
119 ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(), AC)
120 .Val,
122}
123
125 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
126}
127
129 return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
130}
131
133 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
134}
135
136inline IRHandle irhandle_pointee(const Type *ElementType,
137 unsigned AddressSpace) {
138 return std::make_tuple(unifyPtrType(ElementType), AddressSpace,
140}
141
142inline IRHandle irhandle_ptr(const void *Ptr, unsigned Arg,
143 enum SpecialTypeKind STK) {
144 return std::make_tuple(Ptr, Arg, STK);
145}
146
147inline IRHandle irhandle_vkbuffer(const Type *ElementType,
148 StorageClass::StorageClass SC,
149 bool IsWriteable) {
150 return std::make_tuple(ElementType, (SC << 1) | IsWriteable,
152}
153
155 const Type *WrpTy = unifyPtrType(Ty);
156 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_ExplictLayoutType);
157}
158
159inline IRHandle handle(const Type *Ty) {
160 const Type *WrpTy = unifyPtrType(Ty);
161 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_Type);
162}
163
164inline IRHandle handle(const Value *V) {
165 return irhandle_ptr(V, V->getValueID(), STK_Value);
166}
167
168inline IRHandle handle(const MachineInstr *KeyMI) {
169 return irhandle_ptr(KeyMI, SPIRV::to_hash(KeyMI), STK_MachineInstr);
170}
171
172inline bool type_has_layout_decoration(const Type *T) {
173 return (isa<StructType>(T) || isa<ArrayType>(T));
174}
175
176} // namespace SPIRV
177
178// Bi-directional mappings between LLVM entities and (v-reg, machine function)
179// pairs support management of unique SPIR-V definitions per machine function
180// per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
184
185public:
186 bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
187 if (auto DefIt = Defs.find(MI); DefIt != Defs.end()) {
188 auto [ExistHandle, ExistMF] = DefIt->second;
189 if (Handle == ExistHandle && MI->getMF() == ExistMF)
190 return false; // already exists
191 // invalidate the record
192 Vregs.erase(DefIt->second);
193 Defs.erase(DefIt);
194 }
195 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MI->getMF());
197 auto It1 = Vregs.try_emplace(HandleMF, MIKey);
198 if (!It1.second) {
199 // there is an expired record that we need to invalidate
200 Defs.erase(std::get<0>(It1.first->second));
201 // update the record
202 It1.first->second = MIKey;
203 }
204 [[maybe_unused]] auto It2 = Defs.try_emplace(MI, HandleMF);
205 assert(It2.second);
206 return true;
207 }
208 bool erase(const MachineInstr *MI) {
209 bool Res = false;
210 if (auto It = Defs.find(MI); It != Defs.end()) {
211 Res = Vregs.erase(It->second);
212 Defs.erase(It);
213 }
214 return Res;
215 }
217 const MachineFunction *MF) {
218 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MF);
219 auto It = Vregs.find(HandleMF);
220 if (It == Vregs.end())
221 return nullptr;
222 auto [MI, Reg, Hash] = It->second;
223 const MachineInstr *Def = MF->getRegInfo().getVRegDef(Reg);
224 if (!Def || Def != MI || SPIRV::to_hash(MI) != Hash) {
225 // there is an expired record that we need to invalidate
226 erase(MI);
227 return nullptr;
228 }
229 assert(Defs.contains(MI) && Defs.find(MI)->second == HandleMF);
230 return MI;
231 }
233 const MachineInstr *MI = findMI(Handle, MF);
234 return MI ? MI->getOperand(0).getReg() : Register();
235 }
236
237 // helpers
238 bool add(const Type *PointeeTy, unsigned AddressSpace,
239 const MachineInstr *MI) {
240 return add(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MI);
241 }
242 Register find(const Type *PointeeTy, unsigned AddressSpace,
243 const MachineFunction *MF) {
244 return find(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
245 }
246 const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,
247 const MachineFunction *MF) {
248 return findMI(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
249 }
250
251 bool add(const Value *V, const MachineInstr *MI) {
252 return add(SPIRV::handle(V), MI);
253 }
254
255 bool add(const Type *T, bool RequiresExplicitLayout, const MachineInstr *MI) {
256 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T)) {
258 }
259 return add(SPIRV::handle(T), MI);
260 }
261
262 bool add(const MachineInstr *Obj, const MachineInstr *MI) {
263 return add(SPIRV::handle(Obj), MI);
264 }
265
266 Register find(const Value *V, const MachineFunction *MF) {
267 return find(SPIRV::handle(V), MF);
268 }
269
270 Register find(const Type *T, bool RequiresExplicitLayout,
271 const MachineFunction *MF) {
272 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
274 return find(SPIRV::handle(T), MF);
275 }
276
278 return find(SPIRV::handle(MI), MF);
279 }
280
281 const MachineInstr *findMI(const Value *Obj, const MachineFunction *MF) {
282 return findMI(SPIRV::handle(Obj), MF);
283 }
284
285 const MachineInstr *findMI(const Type *T, bool RequiresExplicitLayout,
286 const MachineFunction *MF) {
287 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
289 return findMI(SPIRV::handle(T), MF);
290 }
291
293 const MachineFunction *MF) {
294 return findMI(SPIRV::handle(Obj), MF);
295 }
296};
297} // namespace llvm
298#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:58
#define H(x, y, z)
Definition MD5.cpp:57
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:19
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_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:412
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:548
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:591
struct llvm::SPIRV::ImageAttrs::BitFlags Flags
ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS, unsigned Sampled, unsigned ImageFormat, unsigned AQ=0)