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