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"
19#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
20#include "llvm/CodeGen/MachineFrameInfo.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,
41 SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
42 MachineRegisterInfo &MRI);
43extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
44 MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR,
45 SPIRVTypeInst KnownResType);
46} // namespace llvm
47
48static SPIRVTypeInst deduceIntTypeFromResult(Register ResVReg,
49 MachineIRBuilder &MIB,
50 SPIRVGlobalRegistry *GR) {
51 const LLT &Ty = MIB.getMRI()->getType(Reg: ResVReg);
52 return GR->getOrCreateSPIRVIntegerType(BitWidth: Ty.getScalarSizeInBits(), MIRBuilder&: MIB);
53}
54
55static SPIRVTypeInst deduceTypeFromSingleOperand(MachineInstr *I,
56 MachineIRBuilder &MIB,
57 SPIRVGlobalRegistry *GR,
58 unsigned OpIdx) {
59 Register OpReg = I->getOperand(i: OpIdx).getReg();
60 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(VReg: OpReg)) {
61 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(Type: OpType)) {
62 Register ResVReg = I->getOperand(i: 0).getReg();
63 const LLT &ResLLT = MIB.getMRI()->getType(Reg: ResVReg);
64 if (ResLLT.isVector())
65 return GR->getOrCreateSPIRVVectorType(BaseType: CompType, NumElements: ResLLT.getNumElements(),
66 MIRBuilder&: MIB, EmitIR: false);
67 return CompType;
68 }
69 }
70 return nullptr;
71}
72
73static SPIRVTypeInst deduceTypeFromOperandRange(MachineInstr *I,
74 MachineIRBuilder &MIB,
75 SPIRVGlobalRegistry *GR,
76 unsigned StartOp,
77 unsigned EndOp) {
78 SPIRVTypeInst ResType = nullptr;
79 for (unsigned i = StartOp; i < EndOp; ++i) {
80 if (SPIRVTypeInst Type = deduceTypeFromSingleOperand(I, MIB, GR, OpIdx: 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
92static SPIRVTypeInst deduceTypeFromResultRegister(MachineInstr *Use,
93 Register UseRegister,
94 SPIRVGlobalRegistry *GR,
95 MachineIRBuilder &MIB) {
96 for (const MachineOperand &MO : Use->defs()) {
97 if (!MO.isReg())
98 continue;
99 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(VReg: MO.getReg())) {
100 if (SPIRVTypeInst CompType = GR->getScalarOrVectorComponentType(Type: OpType)) {
101 const LLT &ResLLT = MIB.getMRI()->getType(Reg: UseRegister);
102 if (ResLLT.isVector())
103 return GR->getOrCreateSPIRVVectorType(
104 BaseType: CompType, NumElements: ResLLT.getNumElements(), MIRBuilder&: MIB, EmitIR: false);
105 return CompType;
106 }
107 }
108 }
109 return nullptr;
110}
111
112static SPIRVTypeInst
113deducePointerTypeFromResultRegister(MachineInstr *Use, Register UseRegister,
114 SPIRVGlobalRegistry *GR,
115 MachineIRBuilder &MIB) {
116 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
117 Use->getOpcode() == TargetOpcode::G_STORE);
118
119 Register ValueReg = Use->getOperand(i: 0).getReg();
120 SPIRVTypeInst ValueType = GR->getSPIRVTypeForVReg(VReg: ValueReg);
121 if (!ValueType)
122 return nullptr;
123
124 return GR->getOrCreateSPIRVPointerType(BaseType: ValueType, MIRBuilder&: MIB,
125 SC: SPIRV::StorageClass::Function);
126}
127
128static SPIRVTypeInst deduceTypeFromPointerOperand(MachineInstr *Use,
129 Register UseRegister,
130 SPIRVGlobalRegistry *GR,
131 MachineIRBuilder &MIB) {
132 assert(Use->getOpcode() == TargetOpcode::G_LOAD ||
133 Use->getOpcode() == TargetOpcode::G_STORE);
134
135 Register PtrReg = Use->getOperand(i: 1).getReg();
136 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(VReg: PtrReg);
137 if (!PtrType)
138 return nullptr;
139
140 return GR->getPointeeType(PtrType);
141}
142
143static SPIRVTypeInst deduceTypeFromUses(Register Reg, MachineFunction &MF,
144 SPIRVGlobalRegistry *GR,
145 MachineIRBuilder &MIB) {
146 MachineRegisterInfo &MRI = MF.getRegInfo();
147 for (MachineInstr &Use : MRI.use_nodbg_instructions(Reg)) {
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: &Use, UseRegister: Reg, GR, MIB);
170 break;
171 case TargetOpcode::G_LOAD:
172 case TargetOpcode::G_STORE:
173 if (Reg == Use.getOperand(i: 1).getReg())
174 ResType = deducePointerTypeFromResultRegister(Use: &Use, UseRegister: Reg, GR, MIB);
175 else
176 ResType = deduceTypeFromPointerOperand(Use: &Use, UseRegister: Reg, GR, MIB);
177 break;
178 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
179 case TargetOpcode::G_INTRINSIC: {
180 auto IntrinsicID = cast<GIntrinsic>(Val&: Use).getIntrinsicID();
181 if (IntrinsicID == Intrinsic::spv_insertelt) {
182 if (Reg == Use.getOperand(i: 2).getReg())
183 ResType = deduceTypeFromResultRegister(Use: &Use, UseRegister: Reg, GR, MIB);
184 } else if (IntrinsicID == Intrinsic::spv_extractelt) {
185 if (Reg == Use.getOperand(i: 2).getReg())
186 ResType = deduceTypeFromResultRegister(Use: &Use, UseRegister: 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
199static SPIRVTypeInst deduceGEPType(MachineInstr *I, SPIRVGlobalRegistry *GR,
200 MachineIRBuilder &MIB) {
201 LLVM_DEBUG(dbgs() << "Deducing GEP type for: " << *I);
202 Register PtrReg = I->getOperand(i: 3).getReg();
203 SPIRVTypeInst PtrType = GR->getSPIRVTypeForVReg(VReg: 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(i: 1).getReg();
227 PointeeType = GR->getSPIRVTypeForVReg(VReg: 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(Reg: IdxOp.getReg());
237 if (!Def) {
238 LLVM_DEBUG(
239 dbgs() << " Could not find definition for index register.\n");
240 return nullptr;
241 }
242
243 uint64_t IndexVal = foldImm(MO: 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(i: IndexVal + 1).getReg();
250 PointeeType = GR->getSPIRVTypeForVReg(VReg: 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(Type: PtrType);
266 SPIRVTypeInst Res = GR->getOrCreateSPIRVPointerType(BaseType: PointeeType, MIRBuilder&: MIB, SC);
267 LLVM_DEBUG(dbgs() << " Deduced GEP type: " << *Res);
268 return Res;
269}
270
271static SPIRVTypeInst deduceResultTypeFromOperands(MachineInstr *I,
272 SPIRVGlobalRegistry *GR,
273 MachineIRBuilder &MIB) {
274 Register ResVReg = I->getOperand(i: 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, StartOp: 1, EndOp: I->getNumOperands());
284 case TargetOpcode::G_SHUFFLE_VECTOR:
285 return deduceTypeFromOperandRange(I, MIB, GR, StartOp: 1, EndOp: 3);
286 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
287 case TargetOpcode::G_INTRINSIC: {
288 auto IntrinsicID = cast<GIntrinsic>(Val: 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, OpIdx: 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(i: Idx).getReg();
300 if (SPIRVTypeInst OpType = GR->getSPIRVTypeForVReg(VReg: OpReg))
301 return OpType;
302 }
303 return nullptr;
304 }
305 default:
306 if (I->getNumDefs() == 1 && I->getNumOperands() > 1 &&
307 I->getOperand(i: 1).isReg())
308 return deduceTypeFromSingleOperand(I, MIB, GR, OpIdx: 1);
309 }
310 return nullptr;
311}
312
313static bool deduceAndAssignTypeForGUnmerge(MachineInstr *I, MachineFunction &MF,
314 SPIRVGlobalRegistry *GR,
315 MachineIRBuilder &MIB) {
316 MachineRegisterInfo &MRI = MF.getRegInfo();
317 Register SrcReg = I->getOperand(i: I->getNumOperands() - 1).getReg();
318 SPIRVTypeInst ScalarType = nullptr;
319 if (SPIRVTypeInst DefType = GR->getSPIRVTypeForVReg(VReg: SrcReg)) {
320 assert(DefType->getOpcode() == SPIRV::OpTypeVector);
321 ScalarType = GR->getScalarOrVectorComponentType(Type: 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(Reg: DefReg, MF, GR, MIB);
330 if (ScalarType) {
331 ScalarType = GR->getScalarOrVectorComponentType(Type: 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(VReg: DefReg))
343 continue;
344
345 LLT DefLLT = MRI.getType(Reg: DefReg);
346 SPIRVTypeInst ResType =
347 DefLLT.isVector()
348 ? GR->getOrCreateSPIRVVectorType(
349 BaseType: ScalarType, NumElements: DefLLT.getNumElements(), I&: *I,
350 TII: *MF.getSubtarget<SPIRVSubtarget>().getInstrInfo())
351 : ScalarType;
352 setRegClassType(Reg: DefReg, SpvType: ResType, GR, MRI: &MRI, MF);
353 }
354 return true;
355}
356
357static bool deduceAndAssignSpirvType(MachineInstr *I, MachineFunction &MF,
358 SPIRVGlobalRegistry *GR,
359 MachineIRBuilder &MIB) {
360 LLVM_DEBUG(dbgs() << "\nProcessing instruction: " << *I);
361 MachineRegisterInfo &MRI = MF.getRegInfo();
362 Register ResVReg = I->getOperand(i: 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(Reg: ResVReg, MF, GR, MIB);
375 }
376
377 if (!ResType)
378 return false;
379
380 LLVM_DEBUG(dbgs() << "Assigned type to " << *I << ": " << *ResType);
381 setRegClassType(Reg: ResVReg, SpvType: ResType, GR, MRI: &MRI, MF);
382 return true;
383}
384
385static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR,
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(VReg: ResultRegister)) {
401 LLVM_DEBUG(dbgs() << "Instruction already has a SPIR-V type.\n");
402 if (!MRI.getRegClassOrNull(Reg: ResultRegister)) {
403 LLVM_DEBUG(dbgs() << "Updating the register class.\n");
404 setRegClassType(Reg: ResultRegister, SpvType: GR->getSPIRVTypeForVReg(VReg: ResultRegister),
405 GR, MRI: &MRI, MF: *GR->CurMF, Force: true);
406 }
407 return false;
408 }
409
410 return true;
411}
412
413static void registerSpirvTypeForNewInstructions(MachineFunction &MF,
414 SPIRVGlobalRegistry *GR) {
415 MachineRegisterInfo &MRI = MF.getRegInfo();
416 SmallVector<MachineInstr *, 8> Worklist;
417 for (MachineBasicBlock &MBB : MF) {
418 for (MachineInstr &I : MBB) {
419 if (requiresSpirvType(I, GR, MRI)) {
420 Worklist.push_back(Elt: &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;
436 SmallVector<MachineInstr *, 8> NextWorklist;
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(Elt: 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(i: Idx).getReg();
458 if (GR->getSPIRVTypeForVReg(VReg: ResVReg))
459 continue;
460 const LLT &ResLLT = MRI.getType(Reg: ResVReg);
461 SPIRVTypeInst ResType = nullptr;
462 if (ResLLT.isVector()) {
463 SPIRVTypeInst CompType = GR->getOrCreateSPIRVIntegerType(
464 BitWidth: ResLLT.getElementType().getSizeInBits(), MIRBuilder&: MIB);
465 ResType = GR->getOrCreateSPIRVVectorType(
466 BaseType: CompType, NumElements: ResLLT.getNumElements(), MIRBuilder&: MIB, EmitIR: false);
467 } else {
468 ResType = GR->getOrCreateSPIRVIntegerType(BitWidth: ResLLT.getSizeInBits(), MIRBuilder&: MIB);
469 }
470 setRegClassType(Reg: ResVReg, SpvType: ResType, GR, MRI: &MRI, MF, Force: true);
471 }
472 }
473}
474
475static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI) {
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,
486 SPIRVGlobalRegistry *GR,
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(Reg: ResultRegister, Ty: nullptr, SpirvTy: 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(Ty: MRI.getType(Reg: ResultRegister));
499 const auto *RegClass = GR->getRegClass(SpvType: ResultType);
500 MRI.setRegClass(Reg: NewReg, RC: RegClass);
501 MRI.setRegClass(Reg: ResultRegister, RC: RegClass);
502
503 GR->assignSPIRVTypeToVReg(Type: ResultType, VReg: ResultRegister, MF: 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(Type: ResultType, VReg: NewReg, MF: 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(Opcode: SPIRV::ASSIGN_TYPE)
511 .addDef(RegNo: ResultRegister)
512 .addUse(RegNo: NewReg)
513 .addUse(RegNo: GR->getSPIRVTypeID(SpirvType: ResultType))
514 .setMIFlags(Flags);
515 for (unsigned I = 0, E = MI.getNumDefs(); I != E; ++I) {
516 MachineOperand &MO = MI.getOperand(i: I);
517 if (MO.getReg() == ResultRegister) {
518 MO.setReg(NewReg);
519 break;
520 }
521 }
522}
523
524static void ensureAssignTypeForTypeFolding(MachineFunction &MF,
525 SPIRVGlobalRegistry *GR) {
526 LLVM_DEBUG(dbgs() << "Entering ensureAssignTypeForTypeFolding for function "
527 << MF.getName() << "\n");
528 MachineRegisterInfo &MRI = MF.getRegInfo();
529 for (MachineBasicBlock &MBB : MF) {
530 for (MachineInstr &MI : MBB) {
531 if (!isTypeFoldingSupported(Opcode: MI.getOpcode()))
532 continue;
533
534 LLVM_DEBUG(dbgs() << "Processing instruction: " << MI);
535
536 Register ResultRegister = MI.defs().begin()->getReg();
537 if (hasAssignType(Reg: ResultRegister, MRI)) {
538 LLVM_DEBUG(dbgs() << " Instruction already has ASSIGN_TYPE\n");
539 continue;
540 }
541
542 SPIRVTypeInst ResultType = GR->getSPIRVTypeForVReg(VReg: 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);
553 registerSpirvTypeForNewInstructions(MF, GR);
554 ensureAssignTypeForTypeFolding(MF, GR);
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}
566