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"
24#include "llvm/IR/Analysis.h"
25#include "llvm/IR/IntrinsicsSPIRV.h"
26#include "llvm/Support/Debug.h"
27
28#define DEBUG_TYPE "spirv-postlegalizer"
29
30using namespace llvm;
31
32namespace {
33class SPIRVPostLegalizerLegacy : public MachineFunctionPass {
34public:
35 static char ID;
36 SPIRVPostLegalizerLegacy() : MachineFunctionPass(ID) {}
37 bool runOnMachineFunction(MachineFunction &MF) override;
38};
39} // namespace
40
41namespace llvm {
42// Defined in SPIRVPreLegalizer.cpp.
43extern void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy,
48 SPIRVTypeInst KnownResType);
49} // namespace llvm
50
54 const LLT &Ty = MIB.getMRI()->getType(ResVReg);
55 SPIRVTypeInst ScalarType =
56 GR->getOrCreateSPIRVIntegerType(Ty.getScalarSizeInBits(), MIB);
57 if (Ty.isVector())
58 return GR->getOrCreateSPIRVVectorType(ScalarType, Ty.getNumElements(), MIB,
59 false);
60 return ScalarType;
61}
62
66 unsigned OpIdx) {
67 Register OpReg = I->getOperand(OpIdx).getReg();
68 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg)) {
69 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(OpType)) {
70 Register ResVReg = I->getOperand(0).getReg();
71 const LLT &ResLLT = MIB.getMRI()->getType(ResVReg);
72 if (ResLLT.isVector())
73 return GR->getOrCreateSPIRVVectorType(CompType, ResLLT.getNumElements(),
74 MIB, false);
75 return CompType;
76 }
77 }
78 return nullptr;
79}
80
84 unsigned StartOp,
85 unsigned EndOp) {
86 SPIRVTypeInst ResType = nullptr;
87 for (unsigned i = StartOp; i < EndOp; ++i) {
89#ifdef EXPENSIVE_CHECKS
90 assert(!ResType || Type == ResType && "Conflicting type from operands.");
91 ResType = Type;
92#else
93 return Type;
94#endif
95 }
96 }
97 return ResType;
98}
99
101 Register UseRegister,
103 MachineIRBuilder &MIB) {
104 for (const MachineOperand &MO : Use->defs()) {
105 if (!MO.isReg())
106 continue;
107 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(MO.getReg())) {
108 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(OpType)) {
109 const LLT &ResLLT = MIB.getMRI()->getType(UseRegister);
110 if (ResLLT.isVector())
112 CompType, ResLLT.getNumElements(), MIB, false);
113 return CompType;
114 }
115 }
116 }
117 return nullptr;
118}
119
120static SPIRVTypeInst
123 MachineIRBuilder &MIB) {
124 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
125 Use->getOpcode() == TargetOpcode::G_STORE);
126
127 Register ValueReg = Use->getOperand(0).getReg();
129 if (!ValueType)
130 return nullptr;
131
133 SPIRV::StorageClass::Function);
134}
135
137 Register UseRegister,
139 MachineIRBuilder &MIB) {
140 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
141 Use->getOpcode() == TargetOpcode::G_STORE);
142
143 Register PtrReg = Use->getOperand(1).getReg();
144 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(PtrReg);
145 if (!PtrType)
146 return nullptr;
147
148 return GR->getPointeeType(PtrType);
149}
150
153 MachineIRBuilder &MIB) {
156 SPIRVTypeInst ResType = nullptr;
157 LLVM_DEBUG(dbgs() << "Looking at use " << Use);
158 switch (Use.getOpcode()) {
159 case TargetOpcode::G_BUILD_VECTOR:
160 case TargetOpcode::G_SHUFFLE_VECTOR:
161 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
162 case TargetOpcode::G_UNMERGE_VALUES:
163 case TargetOpcode::G_ADD:
164 case TargetOpcode::G_SUB:
165 case TargetOpcode::G_MUL:
166 case TargetOpcode::G_SDIV:
167 case TargetOpcode::G_UDIV:
168 case TargetOpcode::G_SREM:
169 case TargetOpcode::G_UREM:
170 case TargetOpcode::G_FADD:
171 case TargetOpcode::G_FSUB:
172 case TargetOpcode::G_FMUL:
173 case TargetOpcode::G_FDIV:
174 case TargetOpcode::G_FREM:
175 case TargetOpcode::G_FMA:
176 case TargetOpcode::G_FATAN2:
177 case TargetOpcode::G_FPOW:
178 case TargetOpcode::COPY:
179 case TargetOpcode::G_STRICT_FMA:
180 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
181 break;
182 case TargetOpcode::G_LOAD:
183 case TargetOpcode::G_STORE:
184 if (Reg == Use.getOperand(1).getReg())
185 ResType = deducePointerTypeFromResultRegister(&Use, Reg, GR, MIB);
186 else
187 ResType = deduceTypeFromPointerOperand(&Use, Reg, GR, MIB);
188 break;
189 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
190 case TargetOpcode::G_INTRINSIC: {
191 auto IntrinsicID = cast<GIntrinsic>(Use).getIntrinsicID();
192 if (IntrinsicID == Intrinsic::spv_insertelt) {
193 if (Reg == Use.getOperand(2).getReg())
194 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
195 } else if (IntrinsicID == Intrinsic::spv_extractelt) {
196 if (Reg == Use.getOperand(2).getReg())
197 ResType = deduceTypeFromResultRegister(&Use, Reg, GR, MIB);
198 }
199 break;
200 }
201 }
202 if (ResType) {
203 LLVM_DEBUG(dbgs() << "Deduced type from use " << *ResType);
204 return ResType;
205 }
206 }
207 return nullptr;
208}
209
211 MachineIRBuilder &MIB) {
212 LLVM_DEBUG(dbgs() << "Deducing GEP type for: " << *I);
213 Register PtrReg = I->getOperand(3).getReg();
214 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(PtrReg);
215 if (!PtrType) {
216 LLVM_DEBUG(dbgs() << " Could not get type for pointer operand.\n");
217 return nullptr;
218 }
219
220 SPIRVTypeInst PointeeType = GR->getPointeeType(PtrType);
221 if (!PointeeType) {
222 LLVM_DEBUG(dbgs() << " Could not get pointee type from pointer type.\n");
223 return nullptr;
224 }
225
226 MachineRegisterInfo *MRI = MIB.getMRI();
227
228 // The first index (operand 4) steps over the pointer, so the type doesn't
229 // change.
230 for (unsigned i = 5; i < I->getNumOperands(); ++i) {
231 LLVM_DEBUG(dbgs() << " Traversing index " << i
232 << ", current type: " << *PointeeType);
233 switch (PointeeType->getOpcode()) {
234 case SPIRV::OpTypeArray:
235 case SPIRV::OpTypeRuntimeArray:
236 case SPIRV::OpTypeVector:
237 case SPIRV::OpTypeVectorIdEXT: {
238 Register ElemTypeReg = PointeeType->getOperand(1).getReg();
239 PointeeType = GR->getSPIRVTypeForVReg(ElemTypeReg);
240 break;
241 }
242 case SPIRV::OpTypeStruct: {
243 MachineOperand &IdxOp = I->getOperand(i);
244 if (!IdxOp.isReg()) {
245 LLVM_DEBUG(dbgs() << " Index is not a register.\n");
246 return nullptr;
247 }
248 MachineInstr *Def = MRI->getVRegDef(IdxOp.getReg());
249 if (!Def) {
251 dbgs() << " Could not find definition for index register.\n");
252 return nullptr;
253 }
254
255 uint64_t IndexVal = foldImm(IdxOp, MRI);
256 if (IndexVal >= PointeeType->getNumOperands() - 1) {
257 LLVM_DEBUG(dbgs() << " Struct index out of bounds.\n");
258 return nullptr;
259 }
260
261 Register MemberTypeReg = PointeeType->getOperand(IndexVal + 1).getReg();
262 PointeeType = GR->getSPIRVTypeForVReg(MemberTypeReg);
263 break;
264 }
265 default:
266 LLVM_DEBUG(dbgs() << " Unknown type opcode for GEP traversal.\n");
267 return nullptr;
268 }
269
270 if (!PointeeType) {
271 LLVM_DEBUG(dbgs() << " Could not resolve next pointee type.\n");
272 return nullptr;
273 }
274 }
275 LLVM_DEBUG(dbgs() << " Final pointee type: " << *PointeeType);
276
277 SPIRV::StorageClass::StorageClass SC = GR->getPointerStorageClass(PtrType);
278 SPIRVTypeInst Res = GR->getOrCreateSPIRVPointerType(PointeeType, MIB, SC);
279 LLVM_DEBUG(dbgs() << " Deduced GEP type: " << *Res);
280 return Res;
281}
282
285 MachineIRBuilder &MIB) {
286 Register ResVReg = I->getOperand(0).getReg();
287 switch (I->getOpcode()) {
288 case TargetOpcode::G_CONSTANT:
289 case TargetOpcode::G_ANYEXT:
290 case TargetOpcode::G_SEXT:
291 case TargetOpcode::G_ZEXT:
292 case TargetOpcode::G_TRUNC:
293 return deduceIntTypeFromResult(ResVReg, MIB, GR);
294 case TargetOpcode::G_BUILD_VECTOR:
295 return deduceTypeFromOperandRange(I, MIB, GR, 1, I->getNumOperands());
296 case TargetOpcode::G_SHUFFLE_VECTOR:
297 return deduceTypeFromOperandRange(I, MIB, GR, 1, 3);
298 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
299 case TargetOpcode::G_INTRINSIC: {
300 auto IntrinsicID = cast<GIntrinsic>(I)->getIntrinsicID();
301 if (IntrinsicID == Intrinsic::spv_gep)
302 return deduceGEPType(I, GR, MIB);
303 break;
304 }
305 case TargetOpcode::G_LOAD: {
306 SPIRVTypeInst PtrType = deduceTypeFromSingleOperand(I, MIB, GR, 1);
307 return PtrType ? GR->getPointeeType(PtrType) : nullptr;
308 }
309 case TargetOpcode::G_PHI: {
310 for (unsigned Idx = 1; Idx < I->getNumOperands(); Idx += 2) {
311 Register OpReg = I->getOperand(Idx).getReg();
312 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(OpReg))
313 return OpType;
314 }
315 return nullptr;
316 }
317 default:
318 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&
319 I->getOperand(1).isReg())
320 return deduceTypeFromSingleOperand(I, MIB, GR, 1);
321 }
322 return nullptr;
323}
324
327 MachineIRBuilder &MIB) {
329 Register SrcReg = I->getOperand(I->getNumOperands() - 1).getReg();
330 SPIRVTypeInst ScalarType = nullptr;
331 if (SPIRVTypeInst DefType = GR->getSPIRVTypeForVReg(SrcReg)) {
332 assert(isVectorType(DefType));
333 ScalarType = GR->getScalarOrVectorComponentType(DefType);
334 }
335
336 if (!ScalarType) {
337 // If we could not deduce the type from the source, try to deduce it from
338 // the uses of the results.
339 for (unsigned i = 0; i < I->getNumDefs(); ++i) {
340 Register DefReg = I->getOperand(i).getReg();
341 ScalarType = deduceTypeFromUses(DefReg, MF, GR, MIB);
342 if (ScalarType) {
343 ScalarType = GR->getScalarOrVectorComponentType(ScalarType);
344 break;
345 }
346 }
347 }
348
349 if (!ScalarType)
350 return false;
351
352 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
353 Register DefReg = I->getOperand(i).getReg();
354 if (GR->getSPIRVTypeForVReg(DefReg))
355 continue;
356
357 LLT DefLLT = MRI.getType(DefReg);
358 SPIRVTypeInst ResType =
359 DefLLT.isVector()
361 ScalarType, DefLLT.getNumElements(), *I,
363 : ScalarType;
364 setRegClassType(DefReg, ResType, GR, &MRI, MF);
365 }
366 return true;
367}
368
371 MachineIRBuilder &MIB) {
372 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);
374 Register ResVReg = I->getOperand(0).getReg();
375
376 // G_UNMERGE_VALUES is handled separately because it has multiple definitions,
377 // unlike the other instructions which have a single result register. The main
378 // deduction logic is designed for the single-definition case.
379 if (I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
380 return deduceAndAssignTypeForGUnmerge(I, MF, GR, MIB);
381
382 LLVM_DEBUG(dbgs() << "Inferring type from operands\n");
383 SPIRVTypeInst ResType = deduceResultTypeFromOperands(I, GR, MIB);
384 if (!ResType) {
385 LLVM_DEBUG(dbgs() << "Inferring type from uses\n");
386 ResType = deduceTypeFromUses(ResVReg, MF, GR, MIB);
387 }
388
389 if (!ResType)
390 return false;
391
392 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);
393 setRegClassType(ResVReg, ResType, GR, &MRI, MF);
394 return true;
395}
396
398 MachineRegisterInfo &MRI) {
399 LLVM_DEBUG(dbgs() << "Checking if instruction requires a SPIR-V type: "
400 << I;);
401 if (I.getNumDefs() == 0) {
402 LLVM_DEBUG(dbgs() << "Instruction does not have a definition.\n");
403 return false;
404 }
405
406 if (!I.isPreISelOpcode()) {
407 LLVM_DEBUG(dbgs() << "Instruction is not a generic instruction.\n");
408 return false;
409 }
410
411 Register ResultRegister = I.defs().begin()->getReg();
412 if (GR->getSPIRVTypeForVReg(ResultRegister)) {
413 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");
414 if (!MRI.getRegClassOrNull(ResultRegister)) {
415 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
416 setRegClassType(ResultRegister, GR->getSPIRVTypeForVReg(ResultRegister),
417 GR, &MRI, *GR->CurMF, true);
418 }
419 return false;
420 }
421
422 return true;
423}
424
429 for (MachineBasicBlock &MBB : MF) {
430 for (MachineInstr &I : MBB) {
431 if (requiresSpirvType(I, GR, MRI)) {
432 Worklist.push_back(&I);
433 }
434 }
435 }
436
437 if (Worklist.empty()) {
438 LLVM_DEBUG(dbgs() << "Initial worklist is empty.\n");
439 return;
440 }
441
442 LLVM_DEBUG(dbgs() << "Initial worklist:\n";
443 for (auto *I : Worklist) { I->dump(); });
444
445 bool Changed;
446 do {
447 Changed = false;
449
450 for (MachineInstr *I : Worklist) {
451 MachineIRBuilder MIB(*I);
452 if (deduceAndAssignSpirvType(I, MF, GR, MIB)) {
453 Changed = true;
454 } else {
455 NextWorklist.push_back(I);
456 }
457 }
458 Worklist = std::move(NextWorklist);
459 LLVM_DEBUG(dbgs() << "Worklist size: " << Worklist.size() << "\n");
460 } while (Changed);
461
462 if (Worklist.empty())
463 return;
464
465 for (auto *I : Worklist) {
466 MachineIRBuilder MIB(*I);
467 LLVM_DEBUG(dbgs() << "Assigning default type to results in " << *I);
468 for (unsigned Idx = 0; Idx < I->getNumDefs(); ++Idx) {
469 Register ResVReg = I->getOperand(Idx).getReg();
470 if (GR->getSPIRVTypeForVReg(ResVReg))
471 continue;
472 const LLT &ResLLT = MRI.getType(ResVReg);
473 SPIRVTypeInst ResType = nullptr;
474 if (ResLLT.isVector()) {
476 ResLLT.getElementType().getSizeInBits(), MIB);
477 ResType = GR->getOrCreateSPIRVVectorType(
478 CompType, ResLLT.getNumElements(), MIB, false);
479 } else {
480 ResType = GR->getOrCreateSPIRVIntegerType(ResLLT.getSizeInBits(), MIB);
481 }
482 setRegClassType(ResVReg, ResType, GR, &MRI, MF, true);
483 }
484 }
485}
486
488 for (MachineInstr &UseInstr : MRI.use_nodbg_instructions(Reg)) {
489 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
490 return true;
491 }
492 }
493 return false;
494}
495
496static void generateAssignType(MachineInstr &MI, Register ResultRegister,
497 SPIRVTypeInst ResultType,
499 MachineRegisterInfo &MRI) {
500 LLVM_DEBUG(dbgs() << " Adding ASSIGN_TYPE for ResultRegister: "
501 << printReg(ResultRegister, MRI.getTargetRegisterInfo())
502 << " with type: " << *ResultType);
503 MachineIRBuilder MIB(MI);
504 updateRegType(ResultRegister, nullptr, ResultType, GR, MIB, MRI);
505
506 // Tablegen definition assumes SPIRV::ASSIGN_TYPE pseudo-instruction is
507 // present after each auto-folded instruction to take a type reference
508 // from.
509 Register NewReg =
510 MRI.createGenericVirtualRegister(MRI.getType(ResultRegister));
511 const auto *RegClass = GR->getRegClass(ResultType);
512 MRI.setRegClass(NewReg, RegClass);
513 MRI.setRegClass(ResultRegister, RegClass);
514
515 GR->assignSPIRVTypeToVReg(ResultType, ResultRegister, MIB.getMF());
516 // This is to make it convenient for Legalizer to get the SPIRVType
517 // when processing the actual MI (i.e. not pseudo one).
518 GR->assignSPIRVTypeToVReg(ResultType, NewReg, MIB.getMF());
519 // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to
520 // keep the flags after instruction selection.
521 const uint32_t Flags = MI.getFlags();
522 MIB.buildInstr(SPIRV::ASSIGN_TYPE)
523 .addDef(ResultRegister)
524 .addUse(NewReg)
525 .addUse(GR->getSPIRVTypeID(ResultType))
526 .setMIFlags(Flags);
527 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
528 MachineOperand &MO = MI.getOperand(I);
529 if (MO.getReg() == ResultRegister) {
530 MO.setReg(NewReg);
531 break;
532 }
533 }
534}
535
538 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
539 << MF.getName() << "\n");
541 for (MachineBasicBlock &MBB : MF) {
542 for (MachineInstr &MI : MBB) {
543 if (!isTypeFoldingSupported(MI.getOpcode()))
544 continue;
545
546 LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
547
548 Register ResultRegister = MI.defs().begin()->getReg();
549 if (hasAssignType(ResultRegister, MRI)) {
550 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
551 continue;
552 }
553
554 SPIRVTypeInst ResultType = GR->getSPIRVTypeForVReg(ResultRegister);
555 generateAssignType(MI, ResultRegister, ResultType, GR, MRI);
556 }
557 }
558}
559
561 // Initialize the type registry.
563 SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
564 GR->setCurrentFunc(MF);
567 return true;
568}
569
570INITIALIZE_PASS(SPIRVPostLegalizerLegacy, DEBUG_TYPE, "SPIRV post legalizer",
571 false, false)
572
573char SPIRVPostLegalizerLegacy::ID = 0;
574
576 return new SPIRVPostLegalizerLegacy();
577}
578
579bool SPIRVPostLegalizerLegacy::runOnMachineFunction(MachineFunction &MF) {
580 return runPostLegalizer(MF);
581}
582
583PreservedAnalyses
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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
#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 bool runPostLegalizer(MachineFunction &MF)
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
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
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 LLVM_READONLY 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
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
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
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
bool isTypeFoldingSupported(unsigned Opcode)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
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...
bool isVectorType(SPIRVTypeInst SPVTy)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createSPIRVPostLegalizerLegacyPass()
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.