LLVM 24.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, SPIRVTypeInst SpirvTy,
45 SPIRVTypeInst KnownResType);
46} // namespace llvm
47
51 const LLT &Ty = MIB.getMRI()->getType(ResVReg);
52 SPIRVTypeInst ScalarType =
53 GR->getOrCreateSPIRVIntegerType(Ty.getScalarSizeInBits(), MIB);
54 if (Ty.isVector())
55 return GR->getOrCreateSPIRVVectorType(ScalarType, Ty.getNumElements(), MIB,
56 false);
57 return ScalarType;
58}
59
63 unsigned OpIdx) {
64 Register OpReg = I->getOperand(OpIdx).getReg();
65 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg)) {
66 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(OpType)) {
67 Register ResVReg = I->getOperand(0).getReg();
68 const LLT &ResLLT = MIB.getMRI()->getType(ResVReg);
69 if (ResLLT.isVector())
70 return GR->getOrCreateSPIRVVectorType(CompType, ResLLT.getNumElements(),
71 MIB, false);
72 return CompType;
73 }
74 }
75 return nullptr;
76}
77
81 unsigned StartOp,
82 unsigned EndOp) {
83 SPIRVTypeInst ResType = nullptr;
84 for (unsigned i = StartOp; i < EndOp; ++i) {
86#ifdef EXPENSIVE_CHECKS
87 assert(!ResType || Type == ResType && "Conflicting type from operands.");
88 ResType = Type;
89#else
90 return Type;
91#endif
92 }
93 }
94 return ResType;
95}
96
98 Register UseRegister,
100 MachineIRBuilder &MIB) {
101 for (const MachineOperand &MO : Use->defs()) {
102 if (!MO.isReg())
103 continue;
104 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(MO.getReg())) {
105 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(OpType)) {
106 const LLT &ResLLT = MIB.getMRI()->getType(UseRegister);
107 if (ResLLT.isVector())
109 CompType, ResLLT.getNumElements(), MIB, false);
110 return CompType;
111 }
112 }
113 }
114 return nullptr;
115}
116
117static SPIRVTypeInst
120 MachineIRBuilder &MIB) {
121 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
122 Use->getOpcode() == TargetOpcode::G_STORE);
123
124 Register ValueReg = Use->getOperand(0).getReg();
126 if (!ValueType)
127 return nullptr;
128
130 SPIRV::StorageClass::Function);
131}
132
134 Register UseRegister,
136 MachineIRBuilder &MIB) {
137 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
138 Use->getOpcode() == TargetOpcode::G_STORE);
139
140 Register PtrReg = Use->getOperand(1).getReg();
141 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(PtrReg);
142 if (!PtrType)
143 return nullptr;
144
145 return GR->getPointeeType(PtrType);
146}
147
150 MachineIRBuilder &MIB) {
153 SPIRVTypeInst ResType = nullptr;
154 LLVM_DEBUG(dbgs() << "Looking at use " << Use);
155 switch (Use.getOpcode()) {
156 case TargetOpcode::G_BUILD_VECTOR:
157 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
158 case TargetOpcode::G_UNMERGE_VALUES:
159 case TargetOpcode::G_ADD:
160 case TargetOpcode::G_SUB:
161 case TargetOpcode::G_MUL:
162 case TargetOpcode::G_SDIV:
163 case TargetOpcode::G_UDIV:
164 case TargetOpcode::G_SREM:
165 case TargetOpcode::G_UREM:
166 case TargetOpcode::G_FADD:
167 case TargetOpcode::G_FSUB:
168 case TargetOpcode::G_FMUL:
169 case TargetOpcode::G_FDIV:
170 case TargetOpcode::G_FREM:
171 case TargetOpcode::G_FMA:
172 case TargetOpcode::COPY:
173 case TargetOpcode::G_STRICT_FMA:
174 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
175 break;
176 case TargetOpcode::G_LOAD:
177 case TargetOpcode::G_STORE:
178 if (Reg == Use.getOperand(1).getReg())
179 ResType = deducePointerTypeFromResultRegister(&Use, Reg, GR, MIB);
180 else
181 ResType = deduceTypeFromPointerOperand(&Use, Reg, GR, MIB);
182 break;
183 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
184 case TargetOpcode::G_INTRINSIC: {
185 auto IntrinsicID = cast<GIntrinsic>(Use).getIntrinsicID();
186 if (IntrinsicID == Intrinsic::spv_insertelt) {
187 if (Reg == Use.getOperand(2).getReg())
188 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
189 } else if (IntrinsicID == Intrinsic::spv_extractelt) {
190 if (Reg == Use.getOperand(2).getReg())
191 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
192 }
193 break;
194 }
195 }
196 if (ResType) {
197 LLVM_DEBUG(dbgs() << "Deduced type from use " << *ResType);
198 return ResType;
199 }
200 }
201 return nullptr;
202}
203
205 MachineIRBuilder &MIB) {
206 LLVM_DEBUG(dbgs() << "Deducing GEP type for: " << *I);
207 Register PtrReg = I->getOperand(3).getReg();
208 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(PtrReg);
209 if (!PtrType) {
210 LLVM_DEBUG(dbgs() << " Could not get type for pointer operand.\n");
211 return nullptr;
212 }
213
214 SPIRVTypeInst PointeeType = GR->getPointeeType(PtrType);
215 if (!PointeeType) {
216 LLVM_DEBUG(dbgs() << " Could not get pointee type from pointer type.\n");
217 return nullptr;
218 }
219
220 MachineRegisterInfo *MRI = MIB.getMRI();
221
222 // The first index (operand 4) steps over the pointer, so the type doesn't
223 // change.
224 for (unsigned i = 5; i < I->getNumOperands(); ++i) {
225 LLVM_DEBUG(dbgs() << " Traversing index " << i
226 << ", current type: " << *PointeeType);
227 switch (PointeeType->getOpcode()) {
228 case SPIRV::OpTypeArray:
229 case SPIRV::OpTypeRuntimeArray:
230 case SPIRV::OpTypeVector: {
231 Register ElemTypeReg = PointeeType->getOperand(1).getReg();
232 PointeeType = GR->getSPIRVTypeForVReg(ElemTypeReg);
233 break;
234 }
235 case SPIRV::OpTypeStruct: {
236 MachineOperand &IdxOp = I->getOperand(i);
237 if (!IdxOp.isReg()) {
238 LLVM_DEBUG(dbgs() << " Index is not a register.\n");
239 return nullptr;
240 }
241 MachineInstr *Def = MRI->getVRegDef(IdxOp.getReg());
242 if (!Def) {
244 dbgs() << " Could not find definition for index register.\n");
245 return nullptr;
246 }
247
248 uint64_t IndexVal = foldImm(IdxOp, MRI);
249 if (IndexVal >= PointeeType->getNumOperands() - 1) {
250 LLVM_DEBUG(dbgs() << " Struct index out of bounds.\n");
251 return nullptr;
252 }
253
254 Register MemberTypeReg = PointeeType->getOperand(IndexVal + 1).getReg();
255 PointeeType = GR->getSPIRVTypeForVReg(MemberTypeReg);
256 break;
257 }
258 default:
259 LLVM_DEBUG(dbgs() << " Unknown type opcode for GEP traversal.\n");
260 return nullptr;
261 }
262
263 if (!PointeeType) {
264 LLVM_DEBUG(dbgs() << " Could not resolve next pointee type.\n");
265 return nullptr;
266 }
267 }
268 LLVM_DEBUG(dbgs() << " Final pointee type: " << *PointeeType);
269
270 SPIRV::StorageClass::StorageClass SC = GR->getPointerStorageClass(PtrType);
271 SPIRVTypeInst Res = GR->getOrCreateSPIRVPointerType(PointeeType, MIB, SC);
272 LLVM_DEBUG(dbgs() << " Deduced GEP type: " << *Res);
273 return Res;
274}
275
278 MachineIRBuilder &MIB) {
279 Register ResVReg = I->getOperand(0).getReg();
280 switch (I->getOpcode()) {
281 case TargetOpcode::G_CONSTANT:
282 case TargetOpcode::G_ANYEXT:
283 case TargetOpcode::G_SEXT:
284 case TargetOpcode::G_ZEXT:
285 case TargetOpcode::G_TRUNC:
286 return deduceIntTypeFromResult(ResVReg, MIB, GR);
287 case TargetOpcode::G_BUILD_VECTOR:
288 return deduceTypeFromOperandRange(I, MIB, GR, 1, I->getNumOperands());
289 case TargetOpcode::G_SHUFFLE_VECTOR:
290 return deduceTypeFromOperandRange(I, MIB, GR, 1, 3);
291 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
292 case TargetOpcode::G_INTRINSIC: {
293 auto IntrinsicID = cast<GIntrinsic>(I)->getIntrinsicID();
294 if (IntrinsicID == Intrinsic::spv_gep)
295 return deduceGEPType(I, GR, MIB);
296 break;
297 }
298 case TargetOpcode::G_LOAD: {
299 SPIRVTypeInst PtrType = deduceTypeFromSingleOperand(I, MIB, GR, 1);
300 return PtrType ? GR->getPointeeType(PtrType) : nullptr;
301 }
302 case TargetOpcode::G_PHI: {
303 for (unsigned Idx = 1; Idx < I->getNumOperands(); Idx += 2) {
304 Register OpReg = I->getOperand(Idx).getReg();
305 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg))
306 return OpType;
307 }
308 return nullptr;
309 }
310 default:
311 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&
312 I->getOperand(1).isReg())
313 return deduceTypeFromSingleOperand(I, MIB, GR, 1);
314 }
315 return nullptr;
316}
317
320 MachineIRBuilder &MIB) {
322 Register SrcReg = I->getOperand(I->getNumOperands() - 1).getReg();
323 SPIRVTypeInst ScalarType = nullptr;
324 if (SPIRVTypeInst DefType = GR->getSPIRVTypeForVReg(SrcReg)) {
325 assert(DefType->getOpcode() == SPIRV::OpTypeVector);
326 ScalarType = GR->getScalarOrVectorComponentType(DefType);
327 }
328
329 if (!ScalarType) {
330 // If we could not deduce the type from the source, try to deduce it from
331 // the uses of the results.
332 for (unsigned i = 0; i < I->getNumDefs(); ++i) {
333 Register DefReg = I->getOperand(i).getReg();
334 ScalarType = deduceTypeFromUses(DefReg, MF, GR, MIB);
335 if (ScalarType) {
336 ScalarType = GR->getScalarOrVectorComponentType(ScalarType);
337 break;
338 }
339 }
340 }
341
342 if (!ScalarType)
343 return false;
344
345 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
346 Register DefReg = I->getOperand(i).getReg();
347 if (GR->getSPIRVTypeForVReg(DefReg))
348 continue;
349
350 LLT DefLLT = MRI.getType(DefReg);
351 SPIRVTypeInst ResType =
352 DefLLT.isVector()
354 ScalarType, DefLLT.getNumElements(), *I,
356 : ScalarType;
357 setRegClassType(DefReg, ResType, GR, &MRI, MF);
358 }
359 return true;
360}
361
364 MachineIRBuilder &MIB) {
365 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);
367 Register ResVReg = I->getOperand(0).getReg();
368
369 // G_UNMERGE_VALUES is handled separately because it has multiple definitions,
370 // unlike the other instructions which have a single result register. The main
371 // deduction logic is designed for the single-definition case.
372 if (I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
373 return deduceAndAssignTypeForGUnmerge(I, MF, GR, MIB);
374
375 LLVM_DEBUG(dbgs() << "Inferring type from operands\n");
376 SPIRVTypeInst ResType = deduceResultTypeFromOperands(I, GR, MIB);
377 if (!ResType) {
378 LLVM_DEBUG(dbgs() << "Inferring type from uses\n");
379 ResType = deduceTypeFromUses(ResVReg, MF, GR, MIB);
380 }
381
382 if (!ResType)
383 return false;
384
385 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);
386 setRegClassType(ResVReg, ResType, GR, &MRI, MF);
387 return true;
388}
389
391 MachineRegisterInfo &MRI) {
392 LLVM_DEBUG(dbgs() << "Checking if instruction requires a SPIR-V type: "
393 << I;);
394 if (I.getNumDefs() == 0) {
395 LLVM_DEBUG(dbgs() << "Instruction does not have a definition.\n");
396 return false;
397 }
398
399 if (!I.isPreISelOpcode()) {
400 LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");
401 return false;
402 }
403
404 Register ResultRegister = I.defs().begin()->getReg();
405 if (GR->getSPIRVTypeForVReg(ResultRegister)) {
406 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");
407 if (!MRI.getRegClassOrNull(ResultRegister)) {
408 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
409 setRegClassType(ResultRegister, GR->getSPIRVTypeForVReg(ResultRegister),
410 GR, &MRI, *GR->CurMF, true);
411 }
412 return false;
413 }
414
415 return true;
416}
417
422 for (MachineBasicBlock &MBB : MF) {
423 for (MachineInstr &I : MBB) {
424 if (requiresSpirvType(I, GR, MRI)) {
425 Worklist.push_back(&I);
426 }
427 }
428 }
429
430 if (Worklist.empty()) {
431 LLVM_DEBUG(dbgs() << "Initial worklist is empty.\n");
432 return;
433 }
434
435 LLVM_DEBUG(dbgs() << "Initial worklist:\n";
436 for (auto *I : Worklist) { I->dump(); });
437
438 bool Changed;
439 do {
440 Changed = false;
442
443 for (MachineInstr *I : Worklist) {
444 MachineIRBuilder MIB(*I);
445 if (deduceAndAssignSpirvType(I, MF, GR, MIB)) {
446 Changed = true;
447 } else {
448 NextWorklist.push_back(I);
449 }
450 }
451 Worklist = std::move(NextWorklist);
452 LLVM_DEBUG(dbgs() << "Worklist size: " << Worklist.size() << "\n");
453 } while (Changed);
454
455 if (Worklist.empty())
456 return;
457
458 for (auto *I : Worklist) {
459 MachineIRBuilder MIB(*I);
460 LLVM_DEBUG(dbgs() << "Assigning default type to results in " << *I);
461 for (unsigned Idx = 0; Idx < I->getNumDefs(); ++Idx) {
462 Register ResVReg = I->getOperand(Idx).getReg();
463 if (GR->getSPIRVTypeForVReg(ResVReg))
464 continue;
465 const LLT &ResLLT = MRI.getType(ResVReg);
466 SPIRVTypeInst ResType = nullptr;
467 if (ResLLT.isVector()) {
469 ResLLT.getElementType().getSizeInBits(), MIB);
470 ResType = GR->getOrCreateSPIRVVectorType(
471 CompType, ResLLT.getNumElements(), MIB, false);
472 } else {
473 ResType = GR->getOrCreateSPIRVIntegerType(ResLLT.getSizeInBits(), MIB);
474 }
475 setRegClassType(ResVReg, ResType, GR, &MRI, MF, true);
476 }
477 }
478}
479
481 for (MachineInstr &UseInstr : MRI.use_nodbg_instructions(Reg)) {
482 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
483 return true;
484 }
485 }
486 return false;
487}
488
489static void generateAssignType(MachineInstr &MI, Register ResultRegister,
490 SPIRVTypeInst ResultType,
492 MachineRegisterInfo &MRI) {
493 LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
494 << printReg(ResultRegister, MRI.getTargetRegisterInfo())
495 << " with type: " << *ResultType);
496 MachineIRBuilder MIB(MI);
497 updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
498
499 // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
500 // present after each auto-folded instruction to take a type reference
501 // from.
502 Register NewReg =
503 MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));
504 const auto *RegClass = GR->getRegClass(ResultType);
505 MRI.setRegClass(NewReg, RegClass);
506 MRI.setRegClass(ResultRegister, RegClass);
507
508 GR->assignSPIRVTypeToVReg(ResultType, ResultRegister, MIB.getMF());
509 // This is to make it convenient for Legalizer to get the SPIRVType
510 // when processing the actual MI (i.e. not pseudo one).
511 GR->assignSPIRVTypeToVReg(ResultType, NewReg, MIB.getMF());
512 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to
513 // keep the flags after instruction selection.
514 const uint32_t Flags = MI.getFlags();
515 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
516 .addDef(ResultRegister)
517 .addUse(NewReg)
518 .addUse(GR->getSPIRVTypeID(ResultType))
519 .setMIFlags(Flags);
520 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
521 MachineOperand &MO = MI.getOperand(I);
522 if (MO.getReg() == ResultRegister) {
523 MO.setReg(NewReg);
524 break;
525 }
526 }
527}
528
531 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
532 << MF.getName() << "\n");
534 for (MachineBasicBlock &MBB : MF) {
535 for (MachineInstr &MI : MBB) {
536 if (!isTypeFoldingSupported(MI.getOpcode()))
537 continue;
538
539 LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
540
541 Register ResultRegister = MI.defs().begin()->getReg();
542 if (hasAssignType(ResultRegister, MRI)) {
543 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
544 continue;
545 }
546
547 SPIRVTypeInst ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
548 generateAssignType(MI, ResultRegister, ResultType, GR, MRI);
549 }
550 }
551}
552
553bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
554 // Initialize the type registry.
555 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
556 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
557 GR->setCurrentFunc(MF);
560 return true;
561}
562
563INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false,
564 false)
565
566char SPIRVPostLegalizer::ID = 0;
567
568FunctionPass *llvm::createSPIRVPostLegalizerPass() {
569 return new SPIRVPostLegalizer();
570}
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...
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 SPIRVTypeInst deduceTypeFromPointerOperand(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void registerSpirvTypeForNewInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI)
static SPIRVTypeInst deduceTypeFromOperandRange(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned StartOp, unsigned EndOp)
static SPIRVTypeInst deduceTypeFromResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVTypeInst deduceTypeFromSingleOperand(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned OpIdx)
static SPIRVTypeInst deducePointerTypeFromResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVTypeInst deduceIntTypeFromResult(Register ResVReg, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst deduceGEPType(MachineInstr *I, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void ensureAssignTypeForTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst deduceTypeFromUses(Register Reg, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static bool deduceAndAssignTypeForGUnmerge(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVTypeInst deduceResultTypeFromOperands(MachineInstr *I, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void generateAssignType(MachineInstr &MI, Register ResultRegister, SPIRVTypeInst ResultType, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
#define LLVM_DEBUG(...)
Definition Debug.h:119
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.
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, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
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.
bool isReg() const
isReg - Tests if this is a MO_Register 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,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
const TargetRegisterInfo * getTargetRegisterInfo() const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
SPIRVTypeInst getScalarOrVectorComponentType(SPIRVTypeInst Type) const
SPIRVTypeInst getPointeeType(SPIRVTypeInst PtrType)
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
const SPIRVInstrInfo * getInstrInfo() const override
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:46
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Changed
This is an optimization pass for GlobalISel generic memory operations.
bool isTypeFoldingSupported(unsigned Opcode)
void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning a SPIRV type to a register, ensuring the register class and ty...
FunctionPass * createSPIRVPostLegalizerPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
void setRegClassType(Register Reg, SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVTypeInst KnownResType)
int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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.