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