LLVM 22.0.0git
SPIRVPostLegalizer.cpp
Go to the documentation of this file.
1//===-- SPIRVPostLegalizer.cpp - amend info after legalization -*- 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// The pass partially applies pre-legalization logic to new instructions
10// inserted as a result of legalization:
11// - assigns SPIR-V types to registers for new instructions.
12// - inserts ASSIGN_TYPE pseudo-instructions required for type folding.
13//
14//===----------------------------------------------------------------------===//
15
16#include "SPIRV.h"
17#include "SPIRVSubtarget.h"
18#include "SPIRVUtils.h"
21#include "llvm/IR/IntrinsicsSPIRV.h"
22#include "llvm/Support/Debug.h"
23#include <stack>
24
25#define DEBUG_TYPE "spirv-postlegalizer"
26
27using namespace llvm;
28
29namespace {
30class SPIRVPostLegalizer : public MachineFunctionPass {
31public:
32 static char ID;
33 SPIRVPostLegalizer() : MachineFunctionPass(ID) {}
34 bool runOnMachineFunction(MachineFunction &MF) override;
35};
36} // namespace
37
38namespace llvm {
39// Defined in SPIRVPreLegalizer.cpp.
40extern void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy,
45 SPIRVType *KnownResType);
46} // namespace llvm
47
51 const LLT &Ty = MIB.getMRI()->getType(ResVReg);
52 return GR->getOrCreateSPIRVIntegerType(Ty.getScalarSizeInBits(), MIB);
53}
54
58 unsigned OpIdx) {
59 Register OpReg = I->getOperand(OpIdx).getReg();
60 if (SPIRVType *OpType = GR->getSPIRVTypeForVReg(OpReg)) {
61 if (SPIRVType *CompType = GR->getScalarOrVectorComponentType(OpType)) {
62 Register ResVReg = I->getOperand(0).getReg();
63 const LLT &ResLLT = MIB.getMRI()->getType(ResVReg);
64 if (ResLLT.isVector())
65 return GR->getOrCreateSPIRVVectorType(CompType, ResLLT.getNumElements(),
66 MIB, false);
67 return CompType;
68 }
69 }
70 return nullptr;
71}
72
76 unsigned StartOp, unsigned EndOp) {
77 SPIRVType *ResType = nullptr;
78 for (unsigned i = StartOp; i < EndOp; ++i) {
79 if (SPIRVType *Type = deduceTypeFromSingleOperand(I, MIB, GR, i)) {
80#ifdef EXPENSIVE_CHECKS
81 assert(!ResType || Type == ResType && "Conflicting type from operands.");
82 ResType = Type;
83#else
84 return Type;
85#endif
86 }
87 }
88 return ResType;
89}
90
92 Register UseRegister,
94 MachineIRBuilder &MIB) {
95 for (const MachineOperand &MO : Use->defs()) {
96 if (!MO.isReg())
97 continue;
98 if (SPIRVType *OpType = GR->getSPIRVTypeForVReg(MO.getReg())) {
99 if (SPIRVType *CompType = GR->getScalarOrVectorComponentType(OpType)) {
100 const LLT &ResLLT = MIB.getMRI()->getType(UseRegister);
101 if (ResLLT.isVector())
103 CompType, ResLLT.getNumElements(), MIB, false);
104 return CompType;
105 }
106 }
107 }
108 return nullptr;
109}
110
112 Register UseRegister,
114 MachineIRBuilder &MIB) {
115 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
116 Use->getOpcode() == TargetOpcode::G_STORE);
117
118 Register ValueReg = Use->getOperand(0).getReg();
119 SPIRVType *ValueType = GR->getSPIRVTypeForVReg(ValueReg);
120 if (!ValueType)
121 return nullptr;
122
124 SPIRV::StorageClass::Function);
125}
126
128 Register UseRegister,
130 MachineIRBuilder &MIB) {
131 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
132 Use->getOpcode() == TargetOpcode::G_STORE);
133
134 Register PtrReg = Use->getOperand(1).getReg();
135 SPIRVType *PtrType = GR->getSPIRVTypeForVReg(PtrReg);
136 if (!PtrType)
137 return nullptr;
138
139 return GR->getPointeeType(PtrType);
140}
141
144 MachineIRBuilder &MIB) {
146 for (MachineInstr &Use : MRI.use_nodbg_instructions(Reg)) {
147 SPIRVType *ResType = nullptr;
148 LLVM_DEBUG(dbgs() << "Looking at use " << Use);
149 switch (Use.getOpcode()) {
150 case TargetOpcode::G_BUILD_VECTOR:
151 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
152 case TargetOpcode::G_UNMERGE_VALUES:
153 case TargetOpcode::G_ADD:
154 case TargetOpcode::G_SUB:
155 case TargetOpcode::G_MUL:
156 case TargetOpcode::G_SDIV:
157 case TargetOpcode::G_UDIV:
158 case TargetOpcode::G_SREM:
159 case TargetOpcode::G_UREM:
160 case TargetOpcode::G_FADD:
161 case TargetOpcode::G_FSUB:
162 case TargetOpcode::G_FMUL:
163 case TargetOpcode::G_FDIV:
164 case TargetOpcode::G_FREM:
165 case TargetOpcode::G_FMA:
166 case TargetOpcode::COPY:
167 case TargetOpcode::G_STRICT_FMA:
168 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
169 break;
170 case TargetOpcode::G_LOAD:
171 case TargetOpcode::G_STORE:
172 if (Reg == Use.getOperand(1).getReg())
173 ResType = deducePointerTypeFromResultRegister(&Use, Reg, GR, MIB);
174 else
175 ResType = deduceTypeFromPointerOperand(&Use, Reg, GR, MIB);
176 break;
177 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
178 case TargetOpcode::G_INTRINSIC: {
179 auto IntrinsicID = cast<GIntrinsic>(Use).getIntrinsicID();
180 if (IntrinsicID == Intrinsic::spv_insertelt) {
181 if (Reg == Use.getOperand(2).getReg())
182 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
183 } else if (IntrinsicID == Intrinsic::spv_extractelt) {
184 if (Reg == Use.getOperand(2).getReg())
185 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
186 }
187 break;
188 }
189 }
190 if (ResType) {
191 LLVM_DEBUG(dbgs() << "Deduced type from use " << *ResType);
192 return ResType;
193 }
194 }
195 return nullptr;
196}
197
200 MachineIRBuilder &MIB) {
201 Register ResVReg = I->getOperand(0).getReg();
202 switch (I->getOpcode()) {
203 case TargetOpcode::G_CONSTANT:
204 case TargetOpcode::G_ANYEXT:
205 case TargetOpcode::G_SEXT:
206 case TargetOpcode::G_ZEXT:
207 return deduceIntTypeFromResult(ResVReg, MIB, GR);
208 case TargetOpcode::G_BUILD_VECTOR:
209 return deduceTypeFromOperandRange(I, MIB, GR, 1, I->getNumOperands());
210 case TargetOpcode::G_SHUFFLE_VECTOR:
211 return deduceTypeFromOperandRange(I, MIB, GR, 1, 3);
212 default:
213 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&
214 I->getOperand(1).isReg())
215 return deduceTypeFromSingleOperand(I, MIB, GR, 1);
216 return nullptr;
217 }
218}
219
222 MachineIRBuilder &MIB) {
224 Register SrcReg = I->getOperand(I->getNumOperands() - 1).getReg();
225 SPIRVType *ScalarType = nullptr;
226 if (SPIRVType *DefType = GR->getSPIRVTypeForVReg(SrcReg)) {
227 assert(DefType->getOpcode() == SPIRV::OpTypeVector);
228 ScalarType = GR->getSPIRVTypeForVReg(DefType->getOperand(1).getReg());
229 }
230
231 if (!ScalarType) {
232 // If we could not deduce the type from the source, try to deduce it from
233 // the uses of the results.
234 for (unsigned i = 0; i < I->getNumDefs(); ++i) {
235 Register DefReg = I->getOperand(i).getReg();
236 ScalarType = deduceTypeFromUses(DefReg, MF, GR, MIB);
237 if (ScalarType) {
238 ScalarType = GR->getScalarOrVectorComponentType(ScalarType);
239 break;
240 }
241 }
242 }
243
244 if (!ScalarType)
245 return false;
246
247 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
248 Register DefReg = I->getOperand(i).getReg();
249 if (GR->getSPIRVTypeForVReg(DefReg))
250 continue;
251
252 LLT DefLLT = MRI.getType(DefReg);
253 SPIRVType *ResType =
254 DefLLT.isVector()
256 ScalarType, DefLLT.getNumElements(), *I,
258 : ScalarType;
259 setRegClassType(DefReg, ResType, GR, &MRI, MF);
260 }
261 return true;
262}
263
266 MachineIRBuilder &MIB) {
267 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);
269 Register ResVReg = I->getOperand(0).getReg();
270
271 // G_UNMERGE_VALUES is handled separately because it has multiple definitions,
272 // unlike the other instructions which have a single result register. The main
273 // deduction logic is designed for the single-definition case.
274 if (I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
275 return deduceAndAssignTypeForGUnmerge(I, MF, GR, MIB);
276
277 LLVM_DEBUG(dbgs() << "Inferring type from operands\n");
278 SPIRVType *ResType = deduceResultTypeFromOperands(I, GR, MIB);
279 if (!ResType) {
280 LLVM_DEBUG(dbgs() << "Inferring type from uses\n");
281 ResType = deduceTypeFromUses(ResVReg, MF, GR, MIB);
282 }
283
284 if (!ResType)
285 return false;
286
287 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);
288 GR->assignSPIRVTypeToVReg(ResType, ResVReg, MF);
289
290 if (!MRI.getRegClassOrNull(ResVReg)) {
291 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
292 setRegClassType(ResVReg, ResType, GR, &MRI, *GR->CurMF, true);
293 }
294 return true;
295}
296
299 LLVM_DEBUG(dbgs() << "Checking if instruction requires a SPIR-V type: "
300 << I;);
301 if (I.getNumDefs() == 0) {
302 LLVM_DEBUG(dbgs() << "Instruction does not have a definition.\n");
303 return false;
304 }
305
306 if (!I.isPreISelOpcode()) {
307 LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");
308 return false;
309 }
310
311 Register ResultRegister = I.defs().begin()->getReg();
312 if (GR->getSPIRVTypeForVReg(ResultRegister)) {
313 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");
314 if (!MRI.getRegClassOrNull(ResultRegister)) {
315 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
316 setRegClassType(ResultRegister, GR->getSPIRVTypeForVReg(ResultRegister),
317 GR, &MRI, *GR->CurMF, true);
318 }
319 return false;
320 }
321
322 return true;
323}
324
329 for (MachineBasicBlock &MBB : MF) {
330 for (MachineInstr &I : MBB) {
331 if (requiresSpirvType(I, GR, MRI)) {
332 Worklist.push_back(&I);
333 }
334 }
335 }
336
337 if (Worklist.empty()) {
338 LLVM_DEBUG(dbgs() << "Initial worklist is empty.\n");
339 return;
340 }
341
342 LLVM_DEBUG(dbgs() << "Initial worklist:\n";
343 for (auto *I : Worklist) { I->dump(); });
344
345 bool Changed;
346 do {
347 Changed = false;
349
350 for (MachineInstr *I : Worklist) {
351 MachineIRBuilder MIB(*I);
352 if (deduceAndAssignSpirvType(I, MF, GR, MIB)) {
353 Changed = true;
354 } else {
355 NextWorklist.push_back(I);
356 }
357 }
358 Worklist = std::move(NextWorklist);
359 LLVM_DEBUG(dbgs() << "Worklist size: " << Worklist.size() << "\n");
360 } while (Changed);
361
362 if (Worklist.empty())
363 return;
364
365 for (auto *I : Worklist) {
366 MachineIRBuilder MIB(*I);
367 LLVM_DEBUG(dbgs() << "Assigning default type to results in " << *I);
368 for (unsigned Idx = 0; Idx < I->getNumDefs(); ++Idx) {
369 Register ResVReg = I->getOperand(Idx).getReg();
370 if (GR->getSPIRVTypeForVReg(ResVReg))
371 continue;
372 const LLT &ResLLT = MRI.getType(ResVReg);
373 SPIRVType *ResType = nullptr;
374 if (ResLLT.isVector()) {
376 ResLLT.getElementType().getSizeInBits(), MIB);
377 ResType = GR->getOrCreateSPIRVVectorType(
378 CompType, ResLLT.getNumElements(), MIB, false);
379 } else {
380 ResType = GR->getOrCreateSPIRVIntegerType(ResLLT.getSizeInBits(), MIB);
381 }
382 setRegClassType(ResVReg, ResType, GR, &MRI, MF, true);
383 }
384 }
385}
386
388 for (MachineInstr &UseInstr : MRI.use_nodbg_instructions(Reg)) {
389 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
390 return true;
391 }
392 }
393 return false;
394}
395
396static void generateAssignType(MachineInstr &MI, Register ResultRegister,
397 SPIRVType *ResultType, SPIRVGlobalRegistry *GR,
399 LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
400 << printReg(ResultRegister, MRI.getTargetRegisterInfo())
401 << " with type: " << *ResultType);
402 MachineIRBuilder MIB(MI);
403 updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
404
405 // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
406 // present after each auto-folded instruction to take a type reference
407 // from.
408 Register NewReg =
409 MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));
410 const auto *RegClass = GR->getRegClass(ResultType);
411 MRI.setRegClass(NewReg, RegClass);
412 MRI.setRegClass(ResultRegister, RegClass);
413
414 GR->assignSPIRVTypeToVReg(ResultType, ResultRegister, MIB.getMF());
415 // This is to make it convenient for Legalizer to get the SPIRVType
416 // when processing the actual MI (i.e. not pseudo one).
417 GR->assignSPIRVTypeToVReg(ResultType, NewReg, MIB.getMF());
418 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to
419 // keep the flags after instruction selection.
420 const uint32_t Flags = MI.getFlags();
421 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
422 .addDef(ResultRegister)
423 .addUse(NewReg)
424 .addUse(GR->getSPIRVTypeID(ResultType))
425 .setMIFlags(Flags);
426 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
427 MachineOperand &MO = MI.getOperand(I);
428 if (MO.getReg() == ResultRegister) {
429 MO.setReg(NewReg);
430 break;
431 }
432 }
433}
434
437 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
438 << MF.getName() << "\n");
440 for (MachineBasicBlock &MBB : MF) {
441 for (MachineInstr &MI : MBB) {
442 if (!isTypeFoldingSupported(MI.getOpcode()))
443 continue;
444
445 LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
446
447 Register ResultRegister = MI.defs().begin()->getReg();
448 if (hasAssignType(ResultRegister, MRI)) {
449 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
450 continue;
451 }
452
453 SPIRVType *ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
454 assert(ResultType);
455 generateAssignType(MI, ResultRegister, ResultType, GR, MRI);
456 }
457 }
458}
459
460// Do a preorder traversal of the CFG starting from the BB |Start|.
461// point. Calls |op| on each basic block encountered during the traversal.
463 std::function<void(MachineBasicBlock *)> op) {
464 std::stack<MachineBasicBlock *> ToVisit;
466
467 ToVisit.push(&Start);
468 Seen.insert(ToVisit.top());
469 while (ToVisit.size() != 0) {
470 MachineBasicBlock *MBB = ToVisit.top();
471 ToVisit.pop();
472
473 op(MBB);
474
475 for (auto Succ : MBB->successors()) {
476 if (Seen.contains(Succ))
477 continue;
478 ToVisit.push(Succ);
479 Seen.insert(Succ);
480 }
481 }
482}
483
484// Do a preorder traversal of the CFG starting from the given function's entry
485// point. Calls |op| on each basic block encountered during the traversal.
486void visit(MachineFunction &MF, std::function<void(MachineBasicBlock *)> op) {
487 visit(MF, *MF.begin(), std::move(op));
488}
489
490bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
491 // Initialize the type registry.
492 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
493 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
494 GR->setCurrentFunc(MF);
497 return true;
498}
499
500INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false,
501 false)
502
503char SPIRVPostLegalizer::ID = 0;
504
505FunctionPass *llvm::createSPIRVPostLegalizerPass() {
506 return new SPIRVPostLegalizer();
507}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
#define op(i)
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool deduceAndAssignSpirvType(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceIntTypeFromResult(Register ResVReg, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
static SPIRVType * deduceTypeFromPointerOperand(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void registerSpirvTypeForNewInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI)
static SPIRVType * deduceResultTypeFromOperands(MachineInstr *I, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deducePointerTypeFromResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceTypeFromOperandRange(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned StartOp, unsigned EndOp)
static SPIRVType * deduceTypeFromUses(Register Reg, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceTypeFromResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void generateAssignType(MachineInstr &MI, Register ResultRegister, SPIRVType *ResultType, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
static void ensureAssignTypeForTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static bool deduceAndAssignTypeForGUnmerge(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
static SPIRVType * deduceTypeFromSingleOperand(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned OpIdx)
#define LLVM_DEBUG(...)
Definition Debug.h:114
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
SPIRVType * getPointeeType(SPIRVType *PtrType)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
const SPIRVInstrInfo * getInstrInfo() const override
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
bool isTypeFoldingSupported(unsigned Opcode)
void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVType *KnownResType)
FunctionPass * createSPIRVPostLegalizerPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
const MachineInstr SPIRVType
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.