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