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_SHUFFLE_VECTOR:
158 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
159 case TargetOpcode::G_UNMERGE_VALUES:
160 case TargetOpcode::G_ADD:
161 case TargetOpcode::G_SUB:
162 case TargetOpcode::G_MUL:
163 case TargetOpcode::G_SDIV:
164 case TargetOpcode::G_UDIV:
165 case TargetOpcode::G_SREM:
166 case TargetOpcode::G_UREM:
167 case TargetOpcode::G_FADD:
168 case TargetOpcode::G_FSUB:
169 case TargetOpcode::G_FMUL:
170 case TargetOpcode::G_FDIV:
171 case TargetOpcode::G_FREM:
172 case TargetOpcode::G_FMA:
173 case TargetOpcode::G_FATAN2:
174 case TargetOpcode::G_FPOW:
175 case TargetOpcode::COPY:
176 case TargetOpcode::G_STRICT_FMA:
177 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
178 break;
179 case TargetOpcode::G_LOAD:
180 case TargetOpcode::G_STORE:
181 if (Reg == Use.getOperand(1).getReg())
182 ResType = deducePointerTypeFromResultRegister(&Use, Reg, GR, MIB);
183 else
184 ResType = deduceTypeFromPointerOperand(&Use, Reg, GR, MIB);
185 break;
186 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
187 case TargetOpcode::G_INTRINSIC: {
188 auto IntrinsicID = cast<GIntrinsic>(Use).getIntrinsicID();
189 if (IntrinsicID == Intrinsic::spv_insertelt) {
190 if (Reg == Use.getOperand(2).getReg())
191 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
192 } else if (IntrinsicID == Intrinsic::spv_extractelt) {
193 if (Reg == Use.getOperand(2).getReg())
194 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
195 }
196 break;
197 }
198 }
199 if (ResType) {
200 LLVM_DEBUG(dbgs() << "Deduced type from use " << *ResType);
201 return ResType;
202 }
203 }
204 return nullptr;
205}
206
208 MachineIRBuilder &MIB) {
209 LLVM_DEBUG(dbgs() << "Deducing GEP type for: " << *I);
210 Register PtrReg = I->getOperand(3).getReg();
211 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(PtrReg);
212 if (!PtrType) {
213 LLVM_DEBUG(dbgs() << " Could not get type for pointer operand.\n");
214 return nullptr;
215 }
216
217 SPIRVTypeInst PointeeType = GR->getPointeeType(PtrType);
218 if (!PointeeType) {
219 LLVM_DEBUG(dbgs() << " Could not get pointee type from pointer type.\n");
220 return nullptr;
221 }
222
223 MachineRegisterInfo *MRI = MIB.getMRI();
224
225 // The first index (operand 4) steps over the pointer, so the type doesn't
226 // change.
227 for (unsigned i = 5; i < I->getNumOperands(); ++i) {
228 LLVM_DEBUG(dbgs() << " Traversing index " << i
229 << ", current type: " << *PointeeType);
230 switch (PointeeType->getOpcode()) {
231 case SPIRV::OpTypeArray:
232 case SPIRV::OpTypeRuntimeArray:
233 case SPIRV::OpTypeVector: {
234 Register ElemTypeReg = PointeeType->getOperand(1).getReg();
235 PointeeType = GR->getSPIRVTypeForVReg(ElemTypeReg);
236 break;
237 }
238 case SPIRV::OpTypeStruct: {
239 MachineOperand &IdxOp = I->getOperand(i);
240 if (!IdxOp.isReg()) {
241 LLVM_DEBUG(dbgs() << " Index is not a register.\n");
242 return nullptr;
243 }
244 MachineInstr *Def = MRI->getVRegDef(IdxOp.getReg());
245 if (!Def) {
247 dbgs() << " Could not find definition for index register.\n");
248 return nullptr;
249 }
250
251 uint64_t IndexVal = foldImm(IdxOp, MRI);
252 if (IndexVal >= PointeeType->getNumOperands() - 1) {
253 LLVM_DEBUG(dbgs() << " Struct index out of bounds.\n");
254 return nullptr;
255 }
256
257 Register MemberTypeReg = PointeeType->getOperand(IndexVal + 1).getReg();
258 PointeeType = GR->getSPIRVTypeForVReg(MemberTypeReg);
259 break;
260 }
261 default:
262 LLVM_DEBUG(dbgs() << " Unknown type opcode for GEP traversal.\n");
263 return nullptr;
264 }
265
266 if (!PointeeType) {
267 LLVM_DEBUG(dbgs() << " Could not resolve next pointee type.\n");
268 return nullptr;
269 }
270 }
271 LLVM_DEBUG(dbgs() << " Final pointee type: " << *PointeeType);
272
273 SPIRV::StorageClass::StorageClass SC = GR->getPointerStorageClass(PtrType);
274 SPIRVTypeInst Res = GR->getOrCreateSPIRVPointerType(PointeeType, MIB, SC);
275 LLVM_DEBUG(dbgs() << " Deduced GEP type: " << *Res);
276 return Res;
277}
278
281 MachineIRBuilder &MIB) {
282 Register ResVReg = I->getOperand(0).getReg();
283 switch (I->getOpcode()) {
284 case TargetOpcode::G_CONSTANT:
285 case TargetOpcode::G_ANYEXT:
286 case TargetOpcode::G_SEXT:
287 case TargetOpcode::G_ZEXT:
288 case TargetOpcode::G_TRUNC:
289 return deduceIntTypeFromResult(ResVReg, MIB, GR);
290 case TargetOpcode::G_BUILD_VECTOR:
291 return deduceTypeFromOperandRange(I, MIB, GR, 1, I->getNumOperands());
292 case TargetOpcode::G_SHUFFLE_VECTOR:
293 return deduceTypeFromOperandRange(I, MIB, GR, 1, 3);
294 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
295 case TargetOpcode::G_INTRINSIC: {
296 auto IntrinsicID = cast<GIntrinsic>(I)->getIntrinsicID();
297 if (IntrinsicID == Intrinsic::spv_gep)
298 return deduceGEPType(I, GR, MIB);
299 break;
300 }
301 case TargetOpcode::G_LOAD: {
302 SPIRVTypeInst PtrType = deduceTypeFromSingleOperand(I, MIB, GR, 1);
303 return PtrType ? GR->getPointeeType(PtrType) : nullptr;
304 }
305 case TargetOpcode::G_PHI: {
306 for (unsigned Idx = 1; Idx < I->getNumOperands(); Idx += 2) {
307 Register OpReg = I->getOperand(Idx).getReg();
308 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg))
309 return OpType;
310 }
311 return nullptr;
312 }
313 default:
314 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&
315 I->getOperand(1).isReg())
316 return deduceTypeFromSingleOperand(I, MIB, GR, 1);
317 }
318 return nullptr;
319}
320
323 MachineIRBuilder &MIB) {
325 Register SrcReg = I->getOperand(I->getNumOperands() - 1).getReg();
326 SPIRVTypeInst ScalarType = nullptr;
327 if (SPIRVTypeInst DefType = GR->getSPIRVTypeForVReg(SrcReg)) {
328 assert(DefType->getOpcode() == SPIRV::OpTypeVector);
329 ScalarType = GR->getScalarOrVectorComponentType(DefType);
330 }
331
332 if (!ScalarType) {
333 // If we could not deduce the type from the source, try to deduce it from
334 // the uses of the results.
335 for (unsigned i = 0; i < I->getNumDefs(); ++i) {
336 Register DefReg = I->getOperand(i).getReg();
337 ScalarType = deduceTypeFromUses(DefReg, MF, GR, MIB);
338 if (ScalarType) {
339 ScalarType = GR->getScalarOrVectorComponentType(ScalarType);
340 break;
341 }
342 }
343 }
344
345 if (!ScalarType)
346 return false;
347
348 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
349 Register DefReg = I->getOperand(i).getReg();
350 if (GR->getSPIRVTypeForVReg(DefReg))
351 continue;
352
353 LLT DefLLT = MRI.getType(DefReg);
354 SPIRVTypeInst ResType =
355 DefLLT.isVector()
357 ScalarType, DefLLT.getNumElements(), *I,
359 : ScalarType;
360 setRegClassType(DefReg, ResType, GR, &MRI, MF);
361 }
362 return true;
363}
364
367 MachineIRBuilder &MIB) {
368 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);
370 Register ResVReg = I->getOperand(0).getReg();
371
372 // G_UNMERGE_VALUES is handled separately because it has multiple definitions,
373 // unlike the other instructions which have a single result register. The main
374 // deduction logic is designed for the single-definition case.
375 if (I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
376 return deduceAndAssignTypeForGUnmerge(I, MF, GR, MIB);
377
378 LLVM_DEBUG(dbgs() << "Inferring type from operands\n");
379 SPIRVTypeInst ResType = deduceResultTypeFromOperands(I, GR, MIB);
380 if (!ResType) {
381 LLVM_DEBUG(dbgs() << "Inferring type from uses\n");
382 ResType = deduceTypeFromUses(ResVReg, MF, GR, MIB);
383 }
384
385 if (!ResType)
386 return false;
387
388 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);
389 setRegClassType(ResVReg, ResType, GR, &MRI, MF);
390 return true;
391}
392
394 MachineRegisterInfo &MRI) {
395 LLVM_DEBUG(dbgs() << "Checking if instruction requires a SPIR-V type: "
396 << I;);
397 if (I.getNumDefs() == 0) {
398 LLVM_DEBUG(dbgs() << "Instruction does not have a definition.\n");
399 return false;
400 }
401
402 if (!I.isPreISelOpcode()) {
403 LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");
404 return false;
405 }
406
407 Register ResultRegister = I.defs().begin()->getReg();
408 if (GR->getSPIRVTypeForVReg(ResultRegister)) {
409 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");
410 if (!MRI.getRegClassOrNull(ResultRegister)) {
411 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
412 setRegClassType(ResultRegister, GR->getSPIRVTypeForVReg(ResultRegister),
413 GR, &MRI, *GR->CurMF, true);
414 }
415 return false;
416 }
417
418 return true;
419}
420
425 for (MachineBasicBlock &MBB : MF) {
426 for (MachineInstr &I : MBB) {
427 if (requiresSpirvType(I, GR, MRI)) {
428 Worklist.push_back(&I);
429 }
430 }
431 }
432
433 if (Worklist.empty()) {
434 LLVM_DEBUG(dbgs() << "Initial worklist is empty.\n");
435 return;
436 }
437
438 LLVM_DEBUG(dbgs() << "Initial worklist:\n";
439 for (auto *I : Worklist) { I->dump(); });
440
441 bool Changed;
442 do {
443 Changed = false;
445
446 for (MachineInstr *I : Worklist) {
447 MachineIRBuilder MIB(*I);
448 if (deduceAndAssignSpirvType(I, MF, GR, MIB)) {
449 Changed = true;
450 } else {
451 NextWorklist.push_back(I);
452 }
453 }
454 Worklist = std::move(NextWorklist);
455 LLVM_DEBUG(dbgs() << "Worklist size: " << Worklist.size() << "\n");
456 } while (Changed);
457
458 if (Worklist.empty())
459 return;
460
461 for (auto *I : Worklist) {
462 MachineIRBuilder MIB(*I);
463 LLVM_DEBUG(dbgs() << "Assigning default type to results in " << *I);
464 for (unsigned Idx = 0; Idx < I->getNumDefs(); ++Idx) {
465 Register ResVReg = I->getOperand(Idx).getReg();
466 if (GR->getSPIRVTypeForVReg(ResVReg))
467 continue;
468 const LLT &ResLLT = MRI.getType(ResVReg);
469 SPIRVTypeInst ResType = nullptr;
470 if (ResLLT.isVector()) {
472 ResLLT.getElementType().getSizeInBits(), MIB);
473 ResType = GR->getOrCreateSPIRVVectorType(
474 CompType, ResLLT.getNumElements(), MIB, false);
475 } else {
476 ResType = GR->getOrCreateSPIRVIntegerType(ResLLT.getSizeInBits(), MIB);
477 }
478 setRegClassType(ResVReg, ResType, GR, &MRI, MF, true);
479 }
480 }
481}
482
484 for (MachineInstr &UseInstr : MRI.use_nodbg_instructions(Reg)) {
485 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
486 return true;
487 }
488 }
489 return false;
490}
491
492static void generateAssignType(MachineInstr &MI, Register ResultRegister,
493 SPIRVTypeInst ResultType,
495 MachineRegisterInfo &MRI) {
496 LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
497 << printReg(ResultRegister, MRI.getTargetRegisterInfo())
498 << " with type: " << *ResultType);
499 MachineIRBuilder MIB(MI);
500 updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
501
502 // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
503 // present after each auto-folded instruction to take a type reference
504 // from.
505 Register NewReg =
506 MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));
507 const auto *RegClass = GR->getRegClass(ResultType);
508 MRI.setRegClass(NewReg, RegClass);
509 MRI.setRegClass(ResultRegister, RegClass);
510
511 GR->assignSPIRVTypeToVReg(ResultType, ResultRegister, MIB.getMF());
512 // This is to make it convenient for Legalizer to get the SPIRVType
513 // when processing the actual MI (i.e. not pseudo one).
514 GR->assignSPIRVTypeToVReg(ResultType, NewReg, MIB.getMF());
515 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to
516 // keep the flags after instruction selection.
517 const uint32_t Flags = MI.getFlags();
518 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
519 .addDef(ResultRegister)
520 .addUse(NewReg)
521 .addUse(GR->getSPIRVTypeID(ResultType))
522 .setMIFlags(Flags);
523 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
524 MachineOperand &MO = MI.getOperand(I);
525 if (MO.getReg() == ResultRegister) {
526 MO.setReg(NewReg);
527 break;
528 }
529 }
530}
531
534 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
535 << MF.getName() << "\n");
537 for (MachineBasicBlock &MBB : MF) {
538 for (MachineInstr &MI : MBB) {
539 if (!isTypeFoldingSupported(MI.getOpcode()))
540 continue;
541
542 LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
543
544 Register ResultRegister = MI.defs().begin()->getReg();
545 if (hasAssignType(ResultRegister, MRI)) {
546 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
547 continue;
548 }
549
550 SPIRVTypeInst ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
551 generateAssignType(MI, ResultRegister, ResultType, GR, MRI);
552 }
553 }
554}
555
556bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
557 // Initialize the type registry.
558 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
559 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
560 GR->setCurrentFunc(MF);
563 return true;
564}
565
566INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false,
567 false)
568
569char SPIRVPostLegalizer::ID = 0;
570
571FunctionPass *llvm::createSPIRVPostLegalizerPass() {
572 return new SPIRVPostLegalizer();
573}
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)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC, bool ForceTyped=false)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
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.