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