xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp (revision ba3c1f5972d7b90feb6e6da47905ff2757e0fe57)
1 //===-- SPIRVPreLegalizer.cpp - prepare IR for 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 prepares IR for legalization: it assigns SPIR-V types to registers
10 // and removes intrinsics which holded these types during IR translation.
11 // Also it processes constants and registers them in GR to avoid duplication.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "SPIRV.h"
16 #include "SPIRVSubtarget.h"
17 #include "SPIRVUtils.h"
18 #include "llvm/ADT/PostOrderIterator.h"
19 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
20 #include "llvm/IR/Attributes.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DebugInfoMetadata.h"
23 #include "llvm/IR/IntrinsicsSPIRV.h"
24 #include "llvm/Target/TargetIntrinsicInfo.h"
25 
26 #define DEBUG_TYPE "spirv-prelegalizer"
27 
28 using namespace llvm;
29 
30 namespace {
31 class SPIRVPreLegalizer : public MachineFunctionPass {
32 public:
33   static char ID;
34   SPIRVPreLegalizer() : MachineFunctionPass(ID) {
35     initializeSPIRVPreLegalizerPass(*PassRegistry::getPassRegistry());
36   }
37   bool runOnMachineFunction(MachineFunction &MF) override;
38 };
39 } // namespace
40 
41 static void addConstantsToTrack(MachineFunction &MF, SPIRVGlobalRegistry *GR) {
42   MachineRegisterInfo &MRI = MF.getRegInfo();
43   DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT;
44   SmallVector<MachineInstr *, 10> ToErase, ToEraseComposites;
45   for (MachineBasicBlock &MBB : MF) {
46     for (MachineInstr &MI : MBB) {
47       if (!isSpvIntrinsic(MI, Intrinsic::spv_track_constant))
48         continue;
49       ToErase.push_back(&MI);
50       auto *Const =
51           cast<Constant>(cast<ConstantAsMetadata>(
52                              MI.getOperand(3).getMetadata()->getOperand(0))
53                              ->getValue());
54       if (auto *GV = dyn_cast<GlobalValue>(Const)) {
55         Register Reg = GR->find(GV, &MF);
56         if (!Reg.isValid())
57           GR->add(GV, &MF, MI.getOperand(2).getReg());
58         else
59           RegsAlreadyAddedToDT[&MI] = Reg;
60       } else {
61         Register Reg = GR->find(Const, &MF);
62         if (!Reg.isValid()) {
63           if (auto *ConstVec = dyn_cast<ConstantDataVector>(Const)) {
64             auto *BuildVec = MRI.getVRegDef(MI.getOperand(2).getReg());
65             assert(BuildVec &&
66                    BuildVec->getOpcode() == TargetOpcode::G_BUILD_VECTOR);
67             for (unsigned i = 0; i < ConstVec->getNumElements(); ++i)
68               GR->add(ConstVec->getElementAsConstant(i), &MF,
69                       BuildVec->getOperand(1 + i).getReg());
70           }
71           GR->add(Const, &MF, MI.getOperand(2).getReg());
72         } else {
73           RegsAlreadyAddedToDT[&MI] = Reg;
74           // This MI is unused and will be removed. If the MI uses
75           // const_composite, it will be unused and should be removed too.
76           assert(MI.getOperand(2).isReg() && "Reg operand is expected");
77           MachineInstr *SrcMI = MRI.getVRegDef(MI.getOperand(2).getReg());
78           if (SrcMI && isSpvIntrinsic(*SrcMI, Intrinsic::spv_const_composite))
79             ToEraseComposites.push_back(SrcMI);
80         }
81       }
82     }
83   }
84   for (MachineInstr *MI : ToErase) {
85     Register Reg = MI->getOperand(2).getReg();
86     if (RegsAlreadyAddedToDT.find(MI) != RegsAlreadyAddedToDT.end())
87       Reg = RegsAlreadyAddedToDT[MI];
88     MRI.replaceRegWith(MI->getOperand(0).getReg(), Reg);
89     MI->eraseFromParent();
90   }
91   for (MachineInstr *MI : ToEraseComposites)
92     MI->eraseFromParent();
93 }
94 
95 static void foldConstantsIntoIntrinsics(MachineFunction &MF) {
96   SmallVector<MachineInstr *, 10> ToErase;
97   MachineRegisterInfo &MRI = MF.getRegInfo();
98   const unsigned AssignNameOperandShift = 2;
99   for (MachineBasicBlock &MBB : MF) {
100     for (MachineInstr &MI : MBB) {
101       if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_name))
102         continue;
103       unsigned NumOp = MI.getNumExplicitDefs() + AssignNameOperandShift;
104       while (MI.getOperand(NumOp).isReg()) {
105         MachineOperand &MOp = MI.getOperand(NumOp);
106         MachineInstr *ConstMI = MRI.getVRegDef(MOp.getReg());
107         assert(ConstMI->getOpcode() == TargetOpcode::G_CONSTANT);
108         MI.removeOperand(NumOp);
109         MI.addOperand(MachineOperand::CreateImm(
110             ConstMI->getOperand(1).getCImm()->getZExtValue()));
111         if (MRI.use_empty(ConstMI->getOperand(0).getReg()))
112           ToErase.push_back(ConstMI);
113       }
114     }
115   }
116   for (MachineInstr *MI : ToErase)
117     MI->eraseFromParent();
118 }
119 
120 static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
121                            MachineIRBuilder MIB) {
122   SmallVector<MachineInstr *, 10> ToErase;
123   for (MachineBasicBlock &MBB : MF) {
124     for (MachineInstr &MI : MBB) {
125       if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast))
126         continue;
127       assert(MI.getOperand(2).isReg());
128       MIB.setInsertPt(*MI.getParent(), MI);
129       MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
130       ToErase.push_back(&MI);
131     }
132   }
133   for (MachineInstr *MI : ToErase)
134     MI->eraseFromParent();
135 }
136 
137 // Translating GV, IRTranslator sometimes generates following IR:
138 //   %1 = G_GLOBAL_VALUE
139 //   %2 = COPY %1
140 //   %3 = G_ADDRSPACE_CAST %2
141 // New registers have no SPIRVType and no register class info.
142 //
143 // Set SPIRVType for GV, propagate it from GV to other instructions,
144 // also set register classes.
145 static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
146                                      MachineRegisterInfo &MRI,
147                                      MachineIRBuilder &MIB) {
148   SPIRVType *SpirvTy = nullptr;
149   assert(MI && "Machine instr is expected");
150   if (MI->getOperand(0).isReg()) {
151     Register Reg = MI->getOperand(0).getReg();
152     SpirvTy = GR->getSPIRVTypeForVReg(Reg);
153     if (!SpirvTy) {
154       switch (MI->getOpcode()) {
155       case TargetOpcode::G_CONSTANT: {
156         MIB.setInsertPt(*MI->getParent(), MI);
157         Type *Ty = MI->getOperand(1).getCImm()->getType();
158         SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
159         break;
160       }
161       case TargetOpcode::G_GLOBAL_VALUE: {
162         MIB.setInsertPt(*MI->getParent(), MI);
163         Type *Ty = MI->getOperand(1).getGlobal()->getType();
164         SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
165         break;
166       }
167       case TargetOpcode::G_TRUNC:
168       case TargetOpcode::G_ADDRSPACE_CAST:
169       case TargetOpcode::G_PTR_ADD:
170       case TargetOpcode::COPY: {
171         MachineOperand &Op = MI->getOperand(1);
172         MachineInstr *Def = Op.isReg() ? MRI.getVRegDef(Op.getReg()) : nullptr;
173         if (Def)
174           SpirvTy = propagateSPIRVType(Def, GR, MRI, MIB);
175         break;
176       }
177       default:
178         break;
179       }
180       if (SpirvTy)
181         GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
182       if (!MRI.getRegClassOrNull(Reg))
183         MRI.setRegClass(Reg, &SPIRV::IDRegClass);
184     }
185   }
186   return SpirvTy;
187 }
188 
189 // Insert ASSIGN_TYPE instuction between Reg and its definition, set NewReg as
190 // a dst of the definition, assign SPIRVType to both registers. If SpirvTy is
191 // provided, use it as SPIRVType in ASSIGN_TYPE, otherwise create it from Ty.
192 // It's used also in SPIRVBuiltins.cpp.
193 // TODO: maybe move to SPIRVUtils.
194 namespace llvm {
195 Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
196                            SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB,
197                            MachineRegisterInfo &MRI) {
198   MachineInstr *Def = MRI.getVRegDef(Reg);
199   assert((Ty || SpirvTy) && "Either LLVM or SPIRV type is expected.");
200   MIB.setInsertPt(*Def->getParent(),
201                   (Def->getNextNode() ? Def->getNextNode()->getIterator()
202                                       : Def->getParent()->end()));
203   Register NewReg = MRI.createGenericVirtualRegister(MRI.getType(Reg));
204   if (auto *RC = MRI.getRegClassOrNull(Reg))
205     MRI.setRegClass(NewReg, RC);
206   SpirvTy = SpirvTy ? SpirvTy : GR->getOrCreateSPIRVType(Ty, MIB);
207   GR->assignSPIRVTypeToVReg(SpirvTy, Reg, MIB.getMF());
208   // This is to make it convenient for Legalizer to get the SPIRVType
209   // when processing the actual MI (i.e. not pseudo one).
210   GR->assignSPIRVTypeToVReg(SpirvTy, NewReg, MIB.getMF());
211   // Copy MIFlags from Def to ASSIGN_TYPE instruction. It's required to keep
212   // the flags after instruction selection.
213   const uint16_t Flags = Def->getFlags();
214   MIB.buildInstr(SPIRV::ASSIGN_TYPE)
215       .addDef(Reg)
216       .addUse(NewReg)
217       .addUse(GR->getSPIRVTypeID(SpirvTy))
218       .setMIFlags(Flags);
219   Def->getOperand(0).setReg(NewReg);
220   MRI.setRegClass(Reg, &SPIRV::ANYIDRegClass);
221   return NewReg;
222 }
223 } // namespace llvm
224 
225 static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
226                                  MachineIRBuilder MIB) {
227   MachineRegisterInfo &MRI = MF.getRegInfo();
228   SmallVector<MachineInstr *, 10> ToErase;
229 
230   for (MachineBasicBlock *MBB : post_order(&MF)) {
231     if (MBB->empty())
232       continue;
233 
234     bool ReachedBegin = false;
235     for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
236          !ReachedBegin;) {
237       MachineInstr &MI = *MII;
238 
239       if (isSpvIntrinsic(MI, Intrinsic::spv_assign_type)) {
240         Register Reg = MI.getOperand(1).getReg();
241         Type *Ty = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
242         MachineInstr *Def = MRI.getVRegDef(Reg);
243         assert(Def && "Expecting an instruction that defines the register");
244         // G_GLOBAL_VALUE already has type info.
245         if (Def->getOpcode() != TargetOpcode::G_GLOBAL_VALUE)
246           insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
247         ToErase.push_back(&MI);
248       } else if (MI.getOpcode() == TargetOpcode::G_CONSTANT ||
249                  MI.getOpcode() == TargetOpcode::G_FCONSTANT ||
250                  MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
251         // %rc = G_CONSTANT ty Val
252         // ===>
253         // %cty = OpType* ty
254         // %rctmp = G_CONSTANT ty Val
255         // %rc = ASSIGN_TYPE %rctmp, %cty
256         Register Reg = MI.getOperand(0).getReg();
257         if (MRI.hasOneUse(Reg)) {
258           MachineInstr &UseMI = *MRI.use_instr_begin(Reg);
259           if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) ||
260               isSpvIntrinsic(UseMI, Intrinsic::spv_assign_name))
261             continue;
262         }
263         Type *Ty = nullptr;
264         if (MI.getOpcode() == TargetOpcode::G_CONSTANT)
265           Ty = MI.getOperand(1).getCImm()->getType();
266         else if (MI.getOpcode() == TargetOpcode::G_FCONSTANT)
267           Ty = MI.getOperand(1).getFPImm()->getType();
268         else {
269           assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
270           Type *ElemTy = nullptr;
271           MachineInstr *ElemMI = MRI.getVRegDef(MI.getOperand(1).getReg());
272           assert(ElemMI);
273 
274           if (ElemMI->getOpcode() == TargetOpcode::G_CONSTANT)
275             ElemTy = ElemMI->getOperand(1).getCImm()->getType();
276           else if (ElemMI->getOpcode() == TargetOpcode::G_FCONSTANT)
277             ElemTy = ElemMI->getOperand(1).getFPImm()->getType();
278           else
279             llvm_unreachable("Unexpected opcode");
280           unsigned NumElts =
281               MI.getNumExplicitOperands() - MI.getNumExplicitDefs();
282           Ty = VectorType::get(ElemTy, NumElts, false);
283         }
284         insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
285       } else if (MI.getOpcode() == TargetOpcode::G_TRUNC ||
286                  MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
287                  MI.getOpcode() == TargetOpcode::COPY ||
288                  MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
289         propagateSPIRVType(&MI, GR, MRI, MIB);
290       }
291 
292       if (MII == Begin)
293         ReachedBegin = true;
294       else
295         --MII;
296     }
297   }
298   for (MachineInstr *MI : ToErase)
299     MI->eraseFromParent();
300 }
301 
302 static std::pair<Register, unsigned>
303 createNewIdReg(Register ValReg, unsigned Opcode, MachineRegisterInfo &MRI,
304                const SPIRVGlobalRegistry &GR) {
305   LLT NewT = LLT::scalar(32);
306   SPIRVType *SpvType = GR.getSPIRVTypeForVReg(ValReg);
307   assert(SpvType && "VReg is expected to have SPIRV type");
308   bool IsFloat = SpvType->getOpcode() == SPIRV::OpTypeFloat;
309   bool IsVectorFloat =
310       SpvType->getOpcode() == SPIRV::OpTypeVector &&
311       GR.getSPIRVTypeForVReg(SpvType->getOperand(1).getReg())->getOpcode() ==
312           SPIRV::OpTypeFloat;
313   IsFloat |= IsVectorFloat;
314   auto GetIdOp = IsFloat ? SPIRV::GET_fID : SPIRV::GET_ID;
315   auto DstClass = IsFloat ? &SPIRV::fIDRegClass : &SPIRV::IDRegClass;
316   if (MRI.getType(ValReg).isPointer()) {
317     NewT = LLT::pointer(0, 32);
318     GetIdOp = SPIRV::GET_pID;
319     DstClass = &SPIRV::pIDRegClass;
320   } else if (MRI.getType(ValReg).isVector()) {
321     NewT = LLT::fixed_vector(2, NewT);
322     GetIdOp = IsFloat ? SPIRV::GET_vfID : SPIRV::GET_vID;
323     DstClass = IsFloat ? &SPIRV::vfIDRegClass : &SPIRV::vIDRegClass;
324   }
325   Register IdReg = MRI.createGenericVirtualRegister(NewT);
326   MRI.setRegClass(IdReg, DstClass);
327   return {IdReg, GetIdOp};
328 }
329 
330 static void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
331                          MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR) {
332   unsigned Opc = MI.getOpcode();
333   assert(MI.getNumDefs() > 0 && MRI.hasOneUse(MI.getOperand(0).getReg()));
334   MachineInstr &AssignTypeInst =
335       *(MRI.use_instr_begin(MI.getOperand(0).getReg()));
336   auto NewReg = createNewIdReg(MI.getOperand(0).getReg(), Opc, MRI, *GR).first;
337   AssignTypeInst.getOperand(1).setReg(NewReg);
338   MI.getOperand(0).setReg(NewReg);
339   MIB.setInsertPt(*MI.getParent(),
340                   (MI.getNextNode() ? MI.getNextNode()->getIterator()
341                                     : MI.getParent()->end()));
342   for (auto &Op : MI.operands()) {
343     if (!Op.isReg() || Op.isDef())
344       continue;
345     auto IdOpInfo = createNewIdReg(Op.getReg(), Opc, MRI, *GR);
346     MIB.buildInstr(IdOpInfo.second).addDef(IdOpInfo.first).addUse(Op.getReg());
347     Op.setReg(IdOpInfo.first);
348   }
349 }
350 
351 // Defined in SPIRVLegalizerInfo.cpp.
352 extern bool isTypeFoldingSupported(unsigned Opcode);
353 
354 static void processInstrsWithTypeFolding(MachineFunction &MF,
355                                          SPIRVGlobalRegistry *GR,
356                                          MachineIRBuilder MIB) {
357   MachineRegisterInfo &MRI = MF.getRegInfo();
358   for (MachineBasicBlock &MBB : MF) {
359     for (MachineInstr &MI : MBB) {
360       if (isTypeFoldingSupported(MI.getOpcode()))
361         processInstr(MI, MIB, MRI, GR);
362     }
363   }
364   for (MachineBasicBlock &MBB : MF) {
365     for (MachineInstr &MI : MBB) {
366       // We need to rewrite dst types for ASSIGN_TYPE instrs to be able
367       // to perform tblgen'erated selection and we can't do that on Legalizer
368       // as it operates on gMIR only.
369       if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
370         continue;
371       Register SrcReg = MI.getOperand(1).getReg();
372       unsigned Opcode = MRI.getVRegDef(SrcReg)->getOpcode();
373       if (!isTypeFoldingSupported(Opcode))
374         continue;
375       Register DstReg = MI.getOperand(0).getReg();
376       if (MRI.getType(DstReg).isVector())
377         MRI.setRegClass(DstReg, &SPIRV::IDRegClass);
378       // Don't need to reset type of register holding constant and used in
379       // G_ADDRSPACE_CAST, since it braaks legalizer.
380       if (Opcode == TargetOpcode::G_CONSTANT && MRI.hasOneUse(DstReg)) {
381         MachineInstr &UseMI = *MRI.use_instr_begin(DstReg);
382         if (UseMI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST)
383           continue;
384       }
385       MRI.setType(DstReg, LLT::scalar(32));
386     }
387   }
388 }
389 
390 static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR,
391                             MachineIRBuilder MIB) {
392   // Before IRTranslator pass, calls to spv_switch intrinsic are inserted before
393   // each switch instruction. IRTranslator lowers switches to G_ICMP + G_BRCOND
394   // + G_BR triples. A switch with two cases may be transformed to this MIR
395   // sequence:
396   //
397   //   intrinsic(@llvm.spv.switch), %CmpReg, %Const0, %Const1
398   //   %Dst0 = G_ICMP intpred(eq), %CmpReg, %Const0
399   //   G_BRCOND %Dst0, %bb.2
400   //   G_BR %bb.5
401   // bb.5.entry:
402   //   %Dst1 = G_ICMP intpred(eq), %CmpReg, %Const1
403   //   G_BRCOND %Dst1, %bb.3
404   //   G_BR %bb.4
405   // bb.2.sw.bb:
406   //   ...
407   // bb.3.sw.bb1:
408   //   ...
409   // bb.4.sw.epilog:
410   //   ...
411   //
412   // Sometimes (in case of range-compare switches), additional G_SUBs
413   // instructions are inserted before G_ICMPs. Those need to be additionally
414   // processed and require type assignment.
415   //
416   // This function modifies spv_switch call's operands to include destination
417   // MBBs (default and for each constant value).
418   // Note that this function does not remove G_ICMP + G_BRCOND + G_BR sequences,
419   // but they are marked by ModuleAnalysis as skipped and as a result AsmPrinter
420   // does not output them.
421 
422   MachineRegisterInfo &MRI = MF.getRegInfo();
423 
424   // Collect all MIs relevant to switches across all MBBs in MF.
425   std::vector<MachineInstr *> RelevantInsts;
426 
427   // Temporary set of compare registers. G_SUBs and G_ICMPs relating to
428   // spv_switch use these registers.
429   DenseSet<Register> CompareRegs;
430   for (MachineBasicBlock &MBB : MF) {
431     for (MachineInstr &MI : MBB) {
432       // Calls to spv_switch intrinsics representing IR switches.
433       if (isSpvIntrinsic(MI, Intrinsic::spv_switch)) {
434         assert(MI.getOperand(1).isReg());
435         CompareRegs.insert(MI.getOperand(1).getReg());
436         RelevantInsts.push_back(&MI);
437       }
438 
439       // G_SUBs coming from range-compare switch lowering. G_SUBs are found
440       // after spv_switch but before G_ICMP.
441       if (MI.getOpcode() == TargetOpcode::G_SUB && MI.getOperand(1).isReg() &&
442           CompareRegs.contains(MI.getOperand(1).getReg())) {
443         assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg());
444         Register Dst = MI.getOperand(0).getReg();
445         CompareRegs.insert(Dst);
446         SPIRVType *Ty = GR->getSPIRVTypeForVReg(MI.getOperand(1).getReg());
447         insertAssignInstr(Dst, nullptr, Ty, GR, MIB, MRI);
448       }
449 
450       // G_ICMPs relating to switches.
451       if (MI.getOpcode() == TargetOpcode::G_ICMP && MI.getOperand(2).isReg() &&
452           CompareRegs.contains(MI.getOperand(2).getReg())) {
453         Register Dst = MI.getOperand(0).getReg();
454         // Set type info for destination register of switch's ICMP instruction.
455         if (GR->getSPIRVTypeForVReg(Dst) == nullptr) {
456           MIB.setInsertPt(*MI.getParent(), MI);
457           Type *LLVMTy = IntegerType::get(MF.getFunction().getContext(), 1);
458           SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, MIB);
459           MRI.setRegClass(Dst, &SPIRV::IDRegClass);
460           GR->assignSPIRVTypeToVReg(SpirvTy, Dst, MIB.getMF());
461         }
462         RelevantInsts.push_back(&MI);
463       }
464     }
465   }
466 
467   // Update each spv_switch with destination MBBs.
468   for (auto i = RelevantInsts.begin(); i != RelevantInsts.end(); i++) {
469     if (!isSpvIntrinsic(**i, Intrinsic::spv_switch))
470       continue;
471 
472     // Currently considered spv_switch.
473     MachineInstr *Switch = *i;
474     // Set the first successor as default MBB to support empty switches.
475     MachineBasicBlock *DefaultMBB = *Switch->getParent()->succ_begin();
476     // Container for mapping values to MMBs.
477     SmallDenseMap<uint64_t, MachineBasicBlock *> ValuesToMBBs;
478 
479     // Walk all G_ICMPs to collect ValuesToMBBs. Start at currently considered
480     // spv_switch (i) and break at any spv_switch with the same compare
481     // register (indicating we are back at the same scope).
482     Register CompareReg = Switch->getOperand(1).getReg();
483     for (auto j = i + 1; j != RelevantInsts.end(); j++) {
484       if (isSpvIntrinsic(**j, Intrinsic::spv_switch) &&
485           (*j)->getOperand(1).getReg() == CompareReg)
486         break;
487 
488       if (!((*j)->getOpcode() == TargetOpcode::G_ICMP &&
489             (*j)->getOperand(2).getReg() == CompareReg))
490         continue;
491 
492       MachineInstr *ICMP = *j;
493       Register Dst = ICMP->getOperand(0).getReg();
494       MachineOperand &PredOp = ICMP->getOperand(1);
495       const auto CC = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
496       assert((CC == CmpInst::ICMP_EQ || CC == CmpInst::ICMP_ULE) &&
497              MRI.hasOneUse(Dst) && MRI.hasOneDef(CompareReg));
498       uint64_t Value = getIConstVal(ICMP->getOperand(3).getReg(), &MRI);
499       MachineInstr *CBr = MRI.use_begin(Dst)->getParent();
500       assert(CBr->getOpcode() == SPIRV::G_BRCOND && CBr->getOperand(1).isMBB());
501       MachineBasicBlock *MBB = CBr->getOperand(1).getMBB();
502 
503       // Map switch case Value to target MBB.
504       ValuesToMBBs[Value] = MBB;
505 
506       // The next MI is always G_BR to either the next case or the default.
507       MachineInstr *NextMI = CBr->getNextNode();
508       assert(NextMI->getOpcode() == SPIRV::G_BR &&
509              NextMI->getOperand(0).isMBB());
510       MachineBasicBlock *NextMBB = NextMI->getOperand(0).getMBB();
511       // Default MBB does not begin with G_ICMP using spv_switch compare
512       // register.
513       if (NextMBB->front().getOpcode() != SPIRV::G_ICMP ||
514           (NextMBB->front().getOperand(2).isReg() &&
515            NextMBB->front().getOperand(2).getReg() != CompareReg))
516         DefaultMBB = NextMBB;
517     }
518 
519     // Modify considered spv_switch operands using collected Values and
520     // MBBs.
521     SmallVector<const ConstantInt *, 3> Values;
522     SmallVector<MachineBasicBlock *, 3> MBBs;
523     for (unsigned k = 2; k < Switch->getNumExplicitOperands(); k++) {
524       Register CReg = Switch->getOperand(k).getReg();
525       uint64_t Val = getIConstVal(CReg, &MRI);
526       MachineInstr *ConstInstr = getDefInstrMaybeConstant(CReg, &MRI);
527       if (!ValuesToMBBs[Val])
528         continue;
529 
530       Values.push_back(ConstInstr->getOperand(1).getCImm());
531       MBBs.push_back(ValuesToMBBs[Val]);
532     }
533 
534     for (unsigned k = Switch->getNumExplicitOperands() - 1; k > 1; k--)
535       Switch->removeOperand(k);
536 
537     Switch->addOperand(MachineOperand::CreateMBB(DefaultMBB));
538     for (unsigned k = 0; k < Values.size(); k++) {
539       Switch->addOperand(MachineOperand::CreateCImm(Values[k]));
540       Switch->addOperand(MachineOperand::CreateMBB(MBBs[k]));
541     }
542   }
543 }
544 
545 bool SPIRVPreLegalizer::runOnMachineFunction(MachineFunction &MF) {
546   // Initialize the type registry.
547   const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
548   SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
549   GR->setCurrentFunc(MF);
550   MachineIRBuilder MIB(MF);
551   addConstantsToTrack(MF, GR);
552   foldConstantsIntoIntrinsics(MF);
553   insertBitcasts(MF, GR, MIB);
554   generateAssignInstrs(MF, GR, MIB);
555   processSwitches(MF, GR, MIB);
556   processInstrsWithTypeFolding(MF, GR, MIB);
557 
558   return true;
559 }
560 
561 INITIALIZE_PASS(SPIRVPreLegalizer, DEBUG_TYPE, "SPIRV pre legalizer", false,
562                 false)
563 
564 char SPIRVPreLegalizer::ID = 0;
565 
566 FunctionPass *llvm::createSPIRVPreLegalizerPass() {
567   return new SPIRVPreLegalizer();
568 }
569