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
70
72 struct BitFlags {
73 unsigned Dim : 3;
74 unsigned Depth : 2;
75 unsigned Arrayed : 1;
76 unsigned MS : 1;
77 unsigned Sampled : 2;
78 unsigned ImageFormat : 6;
79 unsigned AQ : 2;
80 } Flags;
81 unsigned Val;
82
83 ImageAttrs(unsigned Dim, unsigned Depth, unsigned Arrayed, unsigned MS,
84 unsigned Sampled, unsigned ImageFormat, unsigned AQ = 0) {
85 Val = 0;
86 Flags.Dim = Dim;
87 Flags.Depth = Depth;
88 Flags.Arrayed = Arrayed;
89 Flags.MS = MS;
90 Flags.Sampled = Sampled;
91 Flags.ImageFormat = ImageFormat;
92 Flags.AQ = AQ;
93 }
94};
95
96inline IRHandle irhandle_image(const Type *SampledTy, unsigned Dim,
97 unsigned Depth, unsigned Arrayed, unsigned MS,
98 unsigned Sampled, unsigned ImageFormat,
99 unsigned AQ = 0) {
100 return std::make_tuple(
101 SampledTy,
102 ImageAttrs(Dim, Depth, Arrayed, MS, Sampled, ImageFormat, AQ).Val,
104}
105
106inline IRHandle irhandle_sampled_image(const Type *SampledTy,
107 const MachineInstr *ImageTy) {
108 assert(ImageTy->getOpcode() == SPIRV::OpTypeImage);
109 unsigned AC = AccessQualifier::AccessQualifier::None;
110 if (ImageTy->getNumOperands() > 8)
111 AC = ImageTy->getOperand(8).getImm();
112 return std::make_tuple(
113 SampledTy,
115 ImageTy->getOperand(2).getImm(), ImageTy->getOperand(3).getImm(),
116 ImageTy->getOperand(4).getImm(), ImageTy->getOperand(5).getImm(),
117 ImageTy->getOperand(6).getImm(), ImageTy->getOperand(7).getImm(), AC)
118 .Val,
120}
121
123 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_Sampler);
124}
125
127 return std::make_tuple(nullptr, AQ, SpecialTypeKind::STK_Pipe);
128}
129
131 return std::make_tuple(nullptr, 0U, SpecialTypeKind::STK_DeviceEvent);
132}
133
134inline IRHandle irhandle_pointee(const Type *ElementType,
135 unsigned AddressSpace) {
136 return std::make_tuple(unifyPtrType(ElementType), AddressSpace,
138}
139
140inline IRHandle irhandle_ptr(const void *Ptr, unsigned Arg,
141 enum SpecialTypeKind STK) {
142 return std::make_tuple(Ptr, Arg, STK);
143}
144
145inline IRHandle irhandle_vkbuffer(const Type *ElementType,
146 StorageClass::StorageClass SC,
147 bool IsWriteable) {
148 return std::make_tuple(ElementType, (SC << 1) | IsWriteable,
150}
151
153 const Type *WrpTy = unifyPtrType(Ty);
154 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_ExplictLayoutType);
155}
156
157inline IRHandle handle(const Type *Ty) {
158 const Type *WrpTy = unifyPtrType(Ty);
159 return irhandle_ptr(WrpTy, Ty->getTypeID(), STK_Type);
160}
161
162inline IRHandle handle(const Value *V) {
163 return irhandle_ptr(V, V->getValueID(), STK_Value);
164}
165
166inline IRHandle handle(const MachineInstr *KeyMI) {
167 return irhandle_ptr(KeyMI, SPIRV::to_hash(KeyMI), STK_MachineInstr);
168}
169
170inline bool type_has_layout_decoration(const Type *T) {
171 return (isa<StructType>(T) || isa<ArrayType>(T));
172}
173
174} // namespace SPIRV
175
176// Bi-directional mappings between LLVM entities and (v-reg, machine function)
177// pairs support management of unique SPIR-V definitions per machine function
178// per an LLVM/GlobalISel entity (e.g., Type, Constant, Machine Instruction).
182
183public:
184 bool add(SPIRV::IRHandle Handle, const MachineInstr *MI) {
185 if (auto DefIt = Defs.find(MI); DefIt != Defs.end()) {
186 auto [ExistHandle, ExistMF] = DefIt->second;
187 if (Handle == ExistHandle && MI->getMF() == ExistMF)
188 return false; // already exists
189 // invalidate the record
190 Vregs.erase(DefIt->second);
191 Defs.erase(DefIt);
192 }
193 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MI->getMF());
195 auto It1 = Vregs.try_emplace(HandleMF, MIKey);
196 if (!It1.second) {
197 // there is an expired record that we need to invalidate
198 Defs.erase(std::get<0>(It1.first->second));
199 // update the record
200 It1.first->second = MIKey;
201 }
202 [[maybe_unused]] auto It2 = Defs.try_emplace(MI, HandleMF);
203 assert(It2.second);
204 return true;
205 }
206 bool erase(const MachineInstr *MI) {
207 bool Res = false;
208 if (auto It = Defs.find(MI); It != Defs.end()) {
209 Res = Vregs.erase(It->second);
210 Defs.erase(It);
211 }
212 return Res;
213 }
215 const MachineFunction *MF) {
216 SPIRV::IRHandleMF HandleMF = SPIRV::getIRHandleMF(Handle, MF);
217 auto It = Vregs.find(HandleMF);
218 if (It == Vregs.end())
219 return nullptr;
220 auto [MI, Reg, Hash] = It->second;
221 const MachineInstr *Def = MF->getRegInfo().getVRegDef(Reg);
222 if (!Def || Def != MI || SPIRV::to_hash(MI) != Hash) {
223 // there is an expired record that we need to invalidate
224 erase(MI);
225 return nullptr;
226 }
227 assert(Defs.contains(MI) && Defs.find(MI)->second == HandleMF);
228 return MI;
229 }
231 const MachineInstr *MI = findMI(Handle, MF);
232 return MI ? MI->getOperand(0).getReg() : Register();
233 }
234
235 // helpers
236 bool add(const Type *PointeeTy, unsigned AddressSpace,
237 const MachineInstr *MI) {
238 return add(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MI);
239 }
240 Register find(const Type *PointeeTy, unsigned AddressSpace,
241 const MachineFunction *MF) {
242 return find(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
243 }
244 const MachineInstr *findMI(const Type *PointeeTy, unsigned AddressSpace,
245 const MachineFunction *MF) {
246 return findMI(SPIRV::irhandle_pointee(PointeeTy, AddressSpace), MF);
247 }
248
249 bool add(const Value *V, const MachineInstr *MI) {
250 return add(SPIRV::handle(V), MI);
251 }
252
253 bool add(const Type *T, bool RequiresExplicitLayout, const MachineInstr *MI) {
254 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T)) {
256 }
257 return add(SPIRV::handle(T), MI);
258 }
259
260 bool add(const MachineInstr *Obj, const MachineInstr *MI) {
261 return add(SPIRV::handle(Obj), MI);
262 }
263
264 Register find(const Value *V, const MachineFunction *MF) {
265 return find(SPIRV::handle(V), MF);
266 }
267
268 Register find(const Type *T, bool RequiresExplicitLayout,
269 const MachineFunction *MF) {
270 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
272 return find(SPIRV::handle(T), MF);
273 }
274
276 return find(SPIRV::handle(MI), MF);
277 }
278
279 const MachineInstr *findMI(const Value *Obj, const MachineFunction *MF) {
280 return findMI(SPIRV::handle(Obj), MF);
281 }
282
283 const MachineInstr *findMI(const Type *T, bool RequiresExplicitLayout,
284 const MachineFunction *MF) {
285 if (RequiresExplicitLayout && SPIRV::type_has_layout_decoration(T))
287 return findMI(SPIRV::handle(T), MF);
288 }
289
291 const MachineFunction *MF) {
292 return findMI(SPIRV::handle(Obj), MF);
293 }
294};
295} // namespace llvm
296#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_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:463
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)