xref: /llvm-project/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp (revision 2bea69bf6503ffc9f3cde9a52b5dac1a25e94e1c)
1 //===- MipsRegisterBankInfo.cpp ---------------------------------*- 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 /// \file
9 /// This file implements the targeting of the RegisterBankInfo class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #include "MipsRegisterBankInfo.h"
14 #include "MipsInstrInfo.h"
15 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
16 #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 
20 #define GET_TARGET_REGBANK_IMPL
21 
22 #include "MipsGenRegisterBank.inc"
23 
24 namespace llvm {
25 namespace Mips {
26 enum PartialMappingIdx {
27   PMI_GPR,
28   PMI_SPR,
29   PMI_DPR,
30   PMI_Min = PMI_GPR,
31 };
32 
33 RegisterBankInfo::PartialMapping PartMappings[]{
34     {0, 32, GPRBRegBank},
35     {0, 32, FPRBRegBank},
36     {0, 64, FPRBRegBank}
37 };
38 
39 enum ValueMappingIdx {
40     InvalidIdx = 0,
41     GPRIdx = 1,
42     SPRIdx = 4,
43     DPRIdx = 7
44 };
45 
46 RegisterBankInfo::ValueMapping ValueMappings[] = {
47     // invalid
48     {nullptr, 0},
49     // up to 3 operands in GPRs
50     {&PartMappings[PMI_GPR - PMI_Min], 1},
51     {&PartMappings[PMI_GPR - PMI_Min], 1},
52     {&PartMappings[PMI_GPR - PMI_Min], 1},
53     // up to 3 ops operands FPRs - single precission
54     {&PartMappings[PMI_SPR - PMI_Min], 1},
55     {&PartMappings[PMI_SPR - PMI_Min], 1},
56     {&PartMappings[PMI_SPR - PMI_Min], 1},
57     // up to 3 ops operands FPRs - double precission
58     {&PartMappings[PMI_DPR - PMI_Min], 1},
59     {&PartMappings[PMI_DPR - PMI_Min], 1},
60     {&PartMappings[PMI_DPR - PMI_Min], 1}
61 };
62 
63 } // end namespace Mips
64 } // end namespace llvm
65 
66 using namespace llvm;
67 
68 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
69     : MipsGenRegisterBankInfo() {}
70 
71 const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
72     const TargetRegisterClass &RC) const {
73   using namespace Mips;
74 
75   switch (RC.getID()) {
76   case Mips::GPR32RegClassID:
77   case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
78   case Mips::GPRMM16MovePPairFirstRegClassID:
79   case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
80   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
81   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
82   case Mips::SP32RegClassID:
83   case Mips::GP32RegClassID:
84     return getRegBank(Mips::GPRBRegBankID);
85   case Mips::FGRCCRegClassID:
86   case Mips::FGR32RegClassID:
87   case Mips::FGR64RegClassID:
88   case Mips::AFGR64RegClassID:
89     return getRegBank(Mips::FPRBRegBankID);
90   default:
91     llvm_unreachable("Register class not supported");
92   }
93 }
94 
95 // Instructions where all register operands are floating point.
96 static bool isFloatingPointOpcode(unsigned Opc) {
97   switch (Opc) {
98   case TargetOpcode::G_FCONSTANT:
99   case TargetOpcode::G_FADD:
100   case TargetOpcode::G_FSUB:
101   case TargetOpcode::G_FMUL:
102   case TargetOpcode::G_FDIV:
103   case TargetOpcode::G_FABS:
104   case TargetOpcode::G_FSQRT:
105   case TargetOpcode::G_FCEIL:
106   case TargetOpcode::G_FFLOOR:
107   case TargetOpcode::G_FPEXT:
108   case TargetOpcode::G_FPTRUNC:
109     return true;
110   default:
111     return false;
112   }
113 }
114 
115 // Instructions where use operands are floating point registers.
116 // Def operands are general purpose.
117 static bool isFloatingPointOpcodeUse(unsigned Opc) {
118   switch (Opc) {
119   case TargetOpcode::G_FPTOSI:
120   case TargetOpcode::G_FPTOUI:
121   case TargetOpcode::G_FCMP:
122   case Mips::MFC1:
123   case Mips::ExtractElementF64:
124   case Mips::ExtractElementF64_64:
125     return true;
126   default:
127     return isFloatingPointOpcode(Opc);
128   }
129 }
130 
131 // Instructions where def operands are floating point registers.
132 // Use operands are general purpose.
133 static bool isFloatingPointOpcodeDef(unsigned Opc) {
134   switch (Opc) {
135   case TargetOpcode::G_SITOFP:
136   case TargetOpcode::G_UITOFP:
137   case Mips::MTC1:
138   case Mips::BuildPairF64:
139   case Mips::BuildPairF64_64:
140     return true;
141   default:
142     return isFloatingPointOpcode(Opc);
143   }
144 }
145 
146 static bool isAmbiguous(unsigned Opc) {
147   switch (Opc) {
148   case TargetOpcode::G_LOAD:
149   case TargetOpcode::G_STORE:
150   case TargetOpcode::G_PHI:
151   case TargetOpcode::G_SELECT:
152     return true;
153   default:
154     return false;
155   }
156 }
157 
158 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
159     Register Reg, const MachineRegisterInfo &MRI) {
160   assert(!MRI.getType(Reg).isPointer() &&
161          "Pointers are gprb, they should not be considered as ambiguous.\n");
162   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
163     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
164     // Copy with many uses.
165     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
166         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
167       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
168     else
169       DefUses.push_back(skipCopiesOutgoing(&UseMI));
170   }
171 }
172 
173 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
174     Register Reg, const MachineRegisterInfo &MRI) {
175   assert(!MRI.getType(Reg).isPointer() &&
176          "Pointers are gprb, they should not be considered as ambiguous.\n");
177   MachineInstr *DefMI = MRI.getVRegDef(Reg);
178   UseDefs.push_back(skipCopiesIncoming(DefMI));
179 }
180 
181 MachineInstr *
182 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
183     MachineInstr *MI) const {
184   const MachineFunction &MF = *MI->getParent()->getParent();
185   const MachineRegisterInfo &MRI = MF.getRegInfo();
186   MachineInstr *Ret = MI;
187   while (Ret->getOpcode() == TargetOpcode::COPY &&
188          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
189          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
190     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
191   }
192   return Ret;
193 }
194 
195 MachineInstr *
196 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
197     MachineInstr *MI) const {
198   const MachineFunction &MF = *MI->getParent()->getParent();
199   const MachineRegisterInfo &MRI = MF.getRegInfo();
200   MachineInstr *Ret = MI;
201   while (Ret->getOpcode() == TargetOpcode::COPY &&
202          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
203     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
204   return Ret;
205 }
206 
207 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
208     const MachineInstr *MI) {
209   assert(isAmbiguous(MI->getOpcode()) &&
210          "Not implemented for non Ambiguous opcode.\n");
211 
212   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
213 
214   if (MI->getOpcode() == TargetOpcode::G_LOAD)
215     addDefUses(MI->getOperand(0).getReg(), MRI);
216 
217   if (MI->getOpcode() == TargetOpcode::G_STORE)
218     addUseDef(MI->getOperand(0).getReg(), MRI);
219 
220   if (MI->getOpcode() == TargetOpcode::G_PHI) {
221     addDefUses(MI->getOperand(0).getReg(), MRI);
222 
223     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
224       addUseDef(MI->getOperand(i).getReg(), MRI);
225   }
226 
227   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
228     addDefUses(MI->getOperand(0).getReg(), MRI);
229 
230     addUseDef(MI->getOperand(2).getReg(), MRI);
231     addUseDef(MI->getOperand(3).getReg(), MRI);
232   }
233 }
234 
235 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
236     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
237   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
238   if (wasVisited(MI))
239     return true; // InstType has already been determined for MI.
240 
241   startVisit(MI);
242   AmbiguousRegDefUseContainer DefUseContainer(MI);
243 
244   // Visit instructions where MI's DEF operands are USED.
245   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
246     return true;
247 
248   // Visit instructions that DEFINE MI's USE operands.
249   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
250     return true;
251 
252   // All MI's adjacent instructions, are ambiguous.
253   if (!WaitingForTypeOfMI) {
254     // This is chain of ambiguous instructions.
255     setTypes(MI, InstType::Ambiguous);
256     return true;
257   }
258   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
259   // instructions or has no other adjacent instructions. Anyway InstType could
260   // not be determined. There could be unexplored path from some of
261   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
262   // mapping available.
263   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
264   // this way when WaitingForTypeOfMI figures out its InstType same InstType
265   // will be assigned to all instructions in this branch.
266   addToWaitingQueue(WaitingForTypeOfMI, MI);
267   return false;
268 }
269 
270 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
271     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
272     bool isDefUse) {
273   while (!AdjacentInstrs.empty()) {
274     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
275 
276     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
277                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
278       setTypes(MI, InstType::FloatingPoint);
279       return true;
280     }
281 
282     // Determine InstType from register bank of phys register that is
283     // 'isDefUse ? def : use' of this copy.
284     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
285       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
286       return true;
287     }
288 
289     // Defaults to integer instruction. Includes G_MERGE_VALUES and
290     // G_UNMERGE_VALUES.
291     if (!isAmbiguous(AdjMI->getOpcode())) {
292       setTypes(MI, InstType::Integer);
293       return true;
294     }
295 
296     // When AdjMI was visited first, MI has to continue to explore remaining
297     // adjacent instructions and determine InstType without visiting AdjMI.
298     if (!wasVisited(AdjMI) ||
299         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
300       if (visit(AdjMI, MI)) {
301         // InstType is successfully determined and is same as for AdjMI.
302         setTypes(MI, getRecordedTypeForInstr(AdjMI));
303         return true;
304       }
305     }
306   }
307   return false;
308 }
309 
310 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
311                                                    InstType InstTy) {
312   changeRecordedTypeForInstr(MI, InstTy);
313   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
314     setTypes(WaitingInstr, InstTy);
315   }
316 }
317 
318 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
319     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
320   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
321          "Copies of non physical registers should not be considered here.\n");
322 
323   const MachineFunction &MF = *CopyInst->getMF();
324   const MachineRegisterInfo &MRI = MF.getRegInfo();
325   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
326   const RegisterBankInfo &RBI =
327       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
328   const RegisterBank *Bank =
329       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
330 
331   if (Bank == &Mips::FPRBRegBank)
332     setTypes(MI, InstType::FloatingPoint);
333   else if (Bank == &Mips::GPRBRegBank)
334     setTypes(MI, InstType::Integer);
335   else
336     llvm_unreachable("Unsupported register bank.\n");
337 }
338 
339 MipsRegisterBankInfo::InstType
340 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
341   visit(MI, nullptr);
342   return getRecordedTypeForInstr(MI);
343 }
344 
345 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
346     llvm::StringRef FunctionName) {
347   if (MFName != FunctionName) {
348     MFName = FunctionName;
349     WaitingQueues.clear();
350     Types.clear();
351   }
352 }
353 
354 const RegisterBankInfo::InstructionMapping &
355 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
356 
357   static TypeInfoForMF TI;
358 
359   // Reset TI internal data when MF changes.
360   TI.cleanupIfNewFunction(MI.getMF()->getName());
361 
362   unsigned Opc = MI.getOpcode();
363   const MachineFunction &MF = *MI.getParent()->getParent();
364   const MachineRegisterInfo &MRI = MF.getRegInfo();
365 
366   if (MI.getOpcode() != TargetOpcode::G_PHI) {
367     const RegisterBankInfo::InstructionMapping &Mapping =
368         getInstrMappingImpl(MI);
369     if (Mapping.isValid())
370       return Mapping;
371   }
372 
373   using namespace TargetOpcode;
374 
375   unsigned NumOperands = MI.getNumOperands();
376   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
377   unsigned MappingID = DefaultMappingID;
378   const unsigned CustomMappingID = 1;
379 
380   switch (Opc) {
381   case G_TRUNC:
382   case G_ADD:
383   case G_SUB:
384   case G_MUL:
385   case G_UMULH:
386   case G_ZEXTLOAD:
387   case G_SEXTLOAD:
388   case G_GEP:
389   case G_INTTOPTR:
390   case G_PTRTOINT:
391   case G_AND:
392   case G_OR:
393   case G_XOR:
394   case G_SHL:
395   case G_ASHR:
396   case G_LSHR:
397   case G_SDIV:
398   case G_UDIV:
399   case G_SREM:
400   case G_UREM:
401     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
402     break;
403   case G_LOAD: {
404     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
405     InstType InstTy = InstType::Integer;
406     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
407       InstTy = TI.determineInstType(&MI);
408     }
409 
410     if (InstTy == InstType::FloatingPoint ||
411         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
412       OperandsMapping =
413           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
414                                          : &Mips::ValueMappings[Mips::DPRIdx],
415                               &Mips::ValueMappings[Mips::GPRIdx]});
416       break;
417     } else { // gprb
418       OperandsMapping =
419           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
420                                          : &Mips::ValueMappings[Mips::DPRIdx],
421                               &Mips::ValueMappings[Mips::GPRIdx]});
422       if (Size == 64)
423         MappingID = CustomMappingID;
424     }
425 
426     break;
427   }
428   case G_STORE: {
429     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
430     InstType InstTy = InstType::Integer;
431     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
432       InstTy = TI.determineInstType(&MI);
433     }
434 
435     if (InstTy == InstType::FloatingPoint ||
436         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
437       OperandsMapping =
438           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
439                                          : &Mips::ValueMappings[Mips::DPRIdx],
440                               &Mips::ValueMappings[Mips::GPRIdx]});
441       break;
442     } else { // gprb
443       OperandsMapping =
444           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
445                                          : &Mips::ValueMappings[Mips::DPRIdx],
446                               &Mips::ValueMappings[Mips::GPRIdx]});
447       if (Size == 64)
448         MappingID = CustomMappingID;
449     }
450     break;
451   }
452   case G_PHI: {
453     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
454     InstType InstTy = InstType::Integer;
455     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
456       InstTy = TI.determineInstType(&MI);
457     }
458 
459     // PHI is copylike and should have one regbank in mapping for def register.
460     if (InstTy == InstType::Integer && Size == 64) { // fprb
461       OperandsMapping =
462           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
463       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
464                                    /*NumOperands=*/1);
465     }
466     // Use default handling for PHI, i.e. set reg bank of def operand to match
467     // register banks of use operands.
468     const RegisterBankInfo::InstructionMapping &Mapping =
469         getInstrMappingImpl(MI);
470     return Mapping;
471   }
472   case G_SELECT: {
473     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
474     InstType InstTy = InstType::Integer;
475     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
476       InstTy = TI.determineInstType(&MI);
477     }
478 
479     if (InstTy == InstType::FloatingPoint ||
480         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
481       const RegisterBankInfo::ValueMapping *Bank =
482           Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
483                      : &Mips::ValueMappings[Mips::DPRIdx];
484       OperandsMapping = getOperandsMapping(
485           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
486       break;
487     } else { // gprb
488       const RegisterBankInfo::ValueMapping *Bank =
489           Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
490                      : &Mips::ValueMappings[Mips::DPRIdx];
491       OperandsMapping = getOperandsMapping(
492           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
493       if (Size == 64)
494         MappingID = CustomMappingID;
495     }
496     break;
497   }
498   case G_UNMERGE_VALUES: {
499     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
500                                           &Mips::ValueMappings[Mips::GPRIdx],
501                                           &Mips::ValueMappings[Mips::DPRIdx]});
502     MappingID = CustomMappingID;
503     break;
504   }
505   case G_MERGE_VALUES: {
506     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
507                                           &Mips::ValueMappings[Mips::GPRIdx],
508                                           &Mips::ValueMappings[Mips::GPRIdx]});
509     MappingID = CustomMappingID;
510     break;
511   }
512   case G_FADD:
513   case G_FSUB:
514   case G_FMUL:
515   case G_FDIV:
516   case G_FABS:
517   case G_FSQRT:{
518     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
519     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
520     OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
521                                  : &Mips::ValueMappings[Mips::DPRIdx];
522     break;
523   }
524   case G_FCONSTANT: {
525     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
526     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
527     const RegisterBankInfo::ValueMapping *FPRValueMapping =
528         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
529                    : &Mips::ValueMappings[Mips::DPRIdx];
530     OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
531     break;
532   }
533   case G_FCMP: {
534     unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
535     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
536     const RegisterBankInfo::ValueMapping *FPRValueMapping =
537         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
538                    : &Mips::ValueMappings[Mips::DPRIdx];
539     OperandsMapping =
540         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
541                             FPRValueMapping, FPRValueMapping});
542     break;
543   }
544   case G_FPEXT:
545     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
546                                           &Mips::ValueMappings[Mips::SPRIdx]});
547     break;
548   case G_FPTRUNC:
549     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
550                                           &Mips::ValueMappings[Mips::DPRIdx]});
551     break;
552   case G_FPTOSI: {
553     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
554     assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
555            "Unsupported integer size");
556     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
557     OperandsMapping = getOperandsMapping({
558         &Mips::ValueMappings[Mips::GPRIdx],
559         SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
560                      : &Mips::ValueMappings[Mips::DPRIdx],
561     });
562     break;
563   }
564   case G_SITOFP: {
565     unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
566     unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
567     (void)SizeInt;
568     assert((SizeInt == 32) && "Unsupported integer size");
569     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
570     OperandsMapping =
571         getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
572                                          : &Mips::ValueMappings[Mips::DPRIdx],
573                             &Mips::ValueMappings[Mips::GPRIdx]});
574     break;
575   }
576   case G_CONSTANT:
577   case G_FRAME_INDEX:
578   case G_GLOBAL_VALUE:
579   case G_BRCOND:
580     OperandsMapping =
581         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
582     break;
583   case G_ICMP:
584     OperandsMapping =
585         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
586                             &Mips::ValueMappings[Mips::GPRIdx],
587                             &Mips::ValueMappings[Mips::GPRIdx]});
588     break;
589   default:
590     return getInvalidInstructionMapping();
591   }
592 
593   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
594                                NumOperands);
595 }
596 
597 using InstListTy = GISelWorkList<4>;
598 namespace {
599 class InstManager : public GISelChangeObserver {
600   InstListTy &InstList;
601 
602 public:
603   InstManager(InstListTy &Insts) : InstList(Insts) {}
604 
605   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
606   void erasingInstr(MachineInstr &MI) override {}
607   void changingInstr(MachineInstr &MI) override {}
608   void changedInstr(MachineInstr &MI) override {}
609 };
610 } // end anonymous namespace
611 
612 /// Here we have to narrowScalar s64 operands to s32, combine away
613 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
614 /// We manually assign 32 bit gprb to register operands of all new instructions
615 /// that got created in the process since they will not end up in RegBankSelect
616 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
617 void MipsRegisterBankInfo::applyMappingImpl(
618     const OperandsMapper &OpdMapper) const {
619   MachineInstr &MI = OpdMapper.getMI();
620   InstListTy NewInstrs;
621   MachineIRBuilder B(MI);
622   MachineFunction *MF = MI.getMF();
623   MachineRegisterInfo &MRI = OpdMapper.getMRI();
624 
625   InstManager NewInstrObserver(NewInstrs);
626   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
627   LegalizerHelper Helper(*MF, WrapperObserver, B);
628   LegalizationArtifactCombiner ArtCombiner(
629       B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
630 
631   switch (MI.getOpcode()) {
632   case TargetOpcode::G_LOAD:
633   case TargetOpcode::G_STORE:
634   case TargetOpcode::G_PHI:
635   case TargetOpcode::G_SELECT: {
636     Helper.narrowScalar(MI, 0, LLT::scalar(32));
637     // Handle new instructions.
638     while (!NewInstrs.empty()) {
639       MachineInstr *NewMI = NewInstrs.pop_back_val();
640       // This is new G_UNMERGE that was created during narrowScalar and will
641       // not be considered for regbank selection. RegBankSelect for mips
642       // visits/makes corresponding G_MERGE first. Combine them here.
643       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
644         SmallVector<MachineInstr *, 2> DeadInstrs;
645         ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
646         for (MachineInstr *DeadMI : DeadInstrs)
647           DeadMI->eraseFromParent();
648       }
649       // This G_MERGE will be combined away when its corresponding G_UNMERGE
650       // gets regBankSelected.
651       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
652         continue;
653       else
654         // Manually set register banks for all register operands to 32 bit gprb.
655         for (auto Op : NewMI->operands()) {
656           if (Op.isReg()) {
657             assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
658                    "Only 32 bit gprb is handled here.\n");
659             MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
660           }
661         }
662     }
663     return;
664   }
665   case TargetOpcode::G_UNMERGE_VALUES: {
666     SmallVector<MachineInstr *, 2> DeadInstrs;
667     ArtCombiner.tryCombineMerges(MI, DeadInstrs);
668     for (MachineInstr *DeadMI : DeadInstrs)
669       DeadMI->eraseFromParent();
670     return;
671   }
672   default:
673     break;
674   }
675 
676   return applyDefaultMapping(OpdMapper);
677 }
678