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