xref: /llvm-project/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp (revision c063b0b0d3346d2a50e2ef28ec0147d6d53f399d)
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   case TargetOpcode::G_IMPLICIT_DEF:
153     return true;
154   default:
155     return false;
156   }
157 }
158 
159 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
160     Register Reg, const MachineRegisterInfo &MRI) {
161   assert(!MRI.getType(Reg).isPointer() &&
162          "Pointers are gprb, they should not be considered as ambiguous.\n");
163   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
164     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
165     // Copy with many uses.
166     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
167         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
168       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
169     else
170       DefUses.push_back(skipCopiesOutgoing(&UseMI));
171   }
172 }
173 
174 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
175     Register Reg, const MachineRegisterInfo &MRI) {
176   assert(!MRI.getType(Reg).isPointer() &&
177          "Pointers are gprb, they should not be considered as ambiguous.\n");
178   MachineInstr *DefMI = MRI.getVRegDef(Reg);
179   UseDefs.push_back(skipCopiesIncoming(DefMI));
180 }
181 
182 MachineInstr *
183 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
184     MachineInstr *MI) const {
185   const MachineFunction &MF = *MI->getParent()->getParent();
186   const MachineRegisterInfo &MRI = MF.getRegInfo();
187   MachineInstr *Ret = MI;
188   while (Ret->getOpcode() == TargetOpcode::COPY &&
189          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
190          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
191     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
192   }
193   return Ret;
194 }
195 
196 MachineInstr *
197 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
198     MachineInstr *MI) const {
199   const MachineFunction &MF = *MI->getParent()->getParent();
200   const MachineRegisterInfo &MRI = MF.getRegInfo();
201   MachineInstr *Ret = MI;
202   while (Ret->getOpcode() == TargetOpcode::COPY &&
203          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
204     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
205   return Ret;
206 }
207 
208 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
209     const MachineInstr *MI) {
210   assert(isAmbiguous(MI->getOpcode()) &&
211          "Not implemented for non Ambiguous opcode.\n");
212 
213   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
214 
215   if (MI->getOpcode() == TargetOpcode::G_LOAD)
216     addDefUses(MI->getOperand(0).getReg(), MRI);
217 
218   if (MI->getOpcode() == TargetOpcode::G_STORE)
219     addUseDef(MI->getOperand(0).getReg(), MRI);
220 
221   if (MI->getOpcode() == TargetOpcode::G_PHI) {
222     addDefUses(MI->getOperand(0).getReg(), MRI);
223 
224     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
225       addUseDef(MI->getOperand(i).getReg(), MRI);
226   }
227 
228   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
229     addDefUses(MI->getOperand(0).getReg(), MRI);
230 
231     addUseDef(MI->getOperand(2).getReg(), MRI);
232     addUseDef(MI->getOperand(3).getReg(), MRI);
233   }
234 
235   if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
236     addDefUses(MI->getOperand(0).getReg(), MRI);
237 }
238 
239 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
240     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
241   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
242   if (wasVisited(MI))
243     return true; // InstType has already been determined for MI.
244 
245   startVisit(MI);
246   AmbiguousRegDefUseContainer DefUseContainer(MI);
247 
248   // Visit instructions where MI's DEF operands are USED.
249   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
250     return true;
251 
252   // Visit instructions that DEFINE MI's USE operands.
253   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
254     return true;
255 
256   // All MI's adjacent instructions, are ambiguous.
257   if (!WaitingForTypeOfMI) {
258     // This is chain of ambiguous instructions.
259     setTypes(MI, InstType::Ambiguous);
260     return true;
261   }
262   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
263   // instructions or has no other adjacent instructions. Anyway InstType could
264   // not be determined. There could be unexplored path from some of
265   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
266   // mapping available.
267   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
268   // this way when WaitingForTypeOfMI figures out its InstType same InstType
269   // will be assigned to all instructions in this branch.
270   addToWaitingQueue(WaitingForTypeOfMI, MI);
271   return false;
272 }
273 
274 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
275     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
276     bool isDefUse) {
277   while (!AdjacentInstrs.empty()) {
278     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
279 
280     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
281                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
282       setTypes(MI, InstType::FloatingPoint);
283       return true;
284     }
285 
286     // Determine InstType from register bank of phys register that is
287     // 'isDefUse ? def : use' of this copy.
288     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
289       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
290       return true;
291     }
292 
293     // Defaults to integer instruction. Includes G_MERGE_VALUES and
294     // G_UNMERGE_VALUES.
295     if (!isAmbiguous(AdjMI->getOpcode())) {
296       setTypes(MI, InstType::Integer);
297       return true;
298     }
299 
300     // When AdjMI was visited first, MI has to continue to explore remaining
301     // adjacent instructions and determine InstType without visiting AdjMI.
302     if (!wasVisited(AdjMI) ||
303         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
304       if (visit(AdjMI, MI)) {
305         // InstType is successfully determined and is same as for AdjMI.
306         setTypes(MI, getRecordedTypeForInstr(AdjMI));
307         return true;
308       }
309     }
310   }
311   return false;
312 }
313 
314 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
315                                                    InstType InstTy) {
316   changeRecordedTypeForInstr(MI, InstTy);
317   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
318     setTypes(WaitingInstr, InstTy);
319   }
320 }
321 
322 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
323     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
324   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
325          "Copies of non physical registers should not be considered here.\n");
326 
327   const MachineFunction &MF = *CopyInst->getMF();
328   const MachineRegisterInfo &MRI = MF.getRegInfo();
329   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
330   const RegisterBankInfo &RBI =
331       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
332   const RegisterBank *Bank =
333       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
334 
335   if (Bank == &Mips::FPRBRegBank)
336     setTypes(MI, InstType::FloatingPoint);
337   else if (Bank == &Mips::GPRBRegBank)
338     setTypes(MI, InstType::Integer);
339   else
340     llvm_unreachable("Unsupported register bank.\n");
341 }
342 
343 MipsRegisterBankInfo::InstType
344 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
345   visit(MI, nullptr);
346   return getRecordedTypeForInstr(MI);
347 }
348 
349 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
350     llvm::StringRef FunctionName) {
351   if (MFName != FunctionName) {
352     MFName = FunctionName;
353     WaitingQueues.clear();
354     Types.clear();
355   }
356 }
357 
358 const RegisterBankInfo::InstructionMapping &
359 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
360 
361   static TypeInfoForMF TI;
362 
363   // Reset TI internal data when MF changes.
364   TI.cleanupIfNewFunction(MI.getMF()->getName());
365 
366   unsigned Opc = MI.getOpcode();
367   const MachineFunction &MF = *MI.getParent()->getParent();
368   const MachineRegisterInfo &MRI = MF.getRegInfo();
369 
370   if (MI.getOpcode() != TargetOpcode::G_PHI) {
371     const RegisterBankInfo::InstructionMapping &Mapping =
372         getInstrMappingImpl(MI);
373     if (Mapping.isValid())
374       return Mapping;
375   }
376 
377   using namespace TargetOpcode;
378 
379   unsigned NumOperands = MI.getNumOperands();
380   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
381   unsigned MappingID = DefaultMappingID;
382   const unsigned CustomMappingID = 1;
383 
384   switch (Opc) {
385   case G_TRUNC:
386   case G_ADD:
387   case G_SUB:
388   case G_MUL:
389   case G_UMULH:
390   case G_ZEXTLOAD:
391   case G_SEXTLOAD:
392   case G_GEP:
393   case G_INTTOPTR:
394   case G_PTRTOINT:
395   case G_AND:
396   case G_OR:
397   case G_XOR:
398   case G_SHL:
399   case G_ASHR:
400   case G_LSHR:
401   case G_SDIV:
402   case G_UDIV:
403   case G_SREM:
404   case G_UREM:
405   case G_BRINDIRECT:
406   case G_VASTART:
407     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
408     break;
409   case G_LOAD: {
410     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
411     InstType InstTy = InstType::Integer;
412     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
413       InstTy = TI.determineInstType(&MI);
414     }
415 
416     if (InstTy == InstType::FloatingPoint ||
417         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
418       OperandsMapping =
419           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
420                                          : &Mips::ValueMappings[Mips::DPRIdx],
421                               &Mips::ValueMappings[Mips::GPRIdx]});
422       break;
423     } else { // gprb
424       OperandsMapping =
425           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
426                                          : &Mips::ValueMappings[Mips::DPRIdx],
427                               &Mips::ValueMappings[Mips::GPRIdx]});
428       if (Size == 64)
429         MappingID = CustomMappingID;
430     }
431 
432     break;
433   }
434   case G_STORE: {
435     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
436     InstType InstTy = InstType::Integer;
437     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
438       InstTy = TI.determineInstType(&MI);
439     }
440 
441     if (InstTy == InstType::FloatingPoint ||
442         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
443       OperandsMapping =
444           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
445                                          : &Mips::ValueMappings[Mips::DPRIdx],
446                               &Mips::ValueMappings[Mips::GPRIdx]});
447       break;
448     } else { // gprb
449       OperandsMapping =
450           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
451                                          : &Mips::ValueMappings[Mips::DPRIdx],
452                               &Mips::ValueMappings[Mips::GPRIdx]});
453       if (Size == 64)
454         MappingID = CustomMappingID;
455     }
456     break;
457   }
458   case G_PHI: {
459     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
460     InstType InstTy = InstType::Integer;
461     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
462       InstTy = TI.determineInstType(&MI);
463     }
464 
465     // PHI is copylike and should have one regbank in mapping for def register.
466     if (InstTy == InstType::Integer && Size == 64) { // fprb
467       OperandsMapping =
468           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
469       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
470                                    /*NumOperands=*/1);
471     }
472     // Use default handling for PHI, i.e. set reg bank of def operand to match
473     // register banks of use operands.
474     const RegisterBankInfo::InstructionMapping &Mapping =
475         getInstrMappingImpl(MI);
476     return Mapping;
477   }
478   case G_SELECT: {
479     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
480     InstType InstTy = InstType::Integer;
481     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
482       InstTy = TI.determineInstType(&MI);
483     }
484 
485     if (InstTy == InstType::FloatingPoint ||
486         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
487       const RegisterBankInfo::ValueMapping *Bank =
488           Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
489                      : &Mips::ValueMappings[Mips::DPRIdx];
490       OperandsMapping = getOperandsMapping(
491           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
492       break;
493     } else { // gprb
494       const RegisterBankInfo::ValueMapping *Bank =
495           Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
496                      : &Mips::ValueMappings[Mips::DPRIdx];
497       OperandsMapping = getOperandsMapping(
498           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
499       if (Size == 64)
500         MappingID = CustomMappingID;
501     }
502     break;
503   }
504   case G_IMPLICIT_DEF: {
505     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
506     InstType InstTy = InstType::Integer;
507     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
508       InstTy = TI.determineInstType(&MI);
509     }
510 
511     if (InstTy == InstType::FloatingPoint) { // fprb
512       OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
513                                    : &Mips::ValueMappings[Mips::DPRIdx];
514     } else { // gprb
515       OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::GPRIdx]
516                                    : &Mips::ValueMappings[Mips::DPRIdx];
517       if (Size == 64)
518         MappingID = CustomMappingID;
519     }
520     break;
521   }
522   case G_UNMERGE_VALUES: {
523     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
524                                           &Mips::ValueMappings[Mips::GPRIdx],
525                                           &Mips::ValueMappings[Mips::DPRIdx]});
526     MappingID = CustomMappingID;
527     break;
528   }
529   case G_MERGE_VALUES: {
530     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
531                                           &Mips::ValueMappings[Mips::GPRIdx],
532                                           &Mips::ValueMappings[Mips::GPRIdx]});
533     MappingID = CustomMappingID;
534     break;
535   }
536   case G_FADD:
537   case G_FSUB:
538   case G_FMUL:
539   case G_FDIV:
540   case G_FABS:
541   case G_FSQRT:{
542     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
543     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
544     OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
545                                  : &Mips::ValueMappings[Mips::DPRIdx];
546     break;
547   }
548   case G_FCONSTANT: {
549     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
550     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
551     const RegisterBankInfo::ValueMapping *FPRValueMapping =
552         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
553                    : &Mips::ValueMappings[Mips::DPRIdx];
554     OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
555     break;
556   }
557   case G_FCMP: {
558     unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
559     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
560     const RegisterBankInfo::ValueMapping *FPRValueMapping =
561         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
562                    : &Mips::ValueMappings[Mips::DPRIdx];
563     OperandsMapping =
564         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
565                             FPRValueMapping, FPRValueMapping});
566     break;
567   }
568   case G_FPEXT:
569     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
570                                           &Mips::ValueMappings[Mips::SPRIdx]});
571     break;
572   case G_FPTRUNC:
573     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
574                                           &Mips::ValueMappings[Mips::DPRIdx]});
575     break;
576   case G_FPTOSI: {
577     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
578     assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
579            "Unsupported integer size");
580     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
581     OperandsMapping = getOperandsMapping({
582         &Mips::ValueMappings[Mips::GPRIdx],
583         SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
584                      : &Mips::ValueMappings[Mips::DPRIdx],
585     });
586     break;
587   }
588   case G_SITOFP: {
589     unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
590     unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
591     (void)SizeInt;
592     assert((SizeInt == 32) && "Unsupported integer size");
593     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
594     OperandsMapping =
595         getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
596                                          : &Mips::ValueMappings[Mips::DPRIdx],
597                             &Mips::ValueMappings[Mips::GPRIdx]});
598     break;
599   }
600   case G_CONSTANT:
601   case G_FRAME_INDEX:
602   case G_GLOBAL_VALUE:
603   case G_JUMP_TABLE:
604   case G_BRCOND:
605     OperandsMapping =
606         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
607     break;
608   case G_BRJT:
609     OperandsMapping =
610         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
611                             &Mips::ValueMappings[Mips::GPRIdx]});
612     break;
613   case G_ICMP:
614     OperandsMapping =
615         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
616                             &Mips::ValueMappings[Mips::GPRIdx],
617                             &Mips::ValueMappings[Mips::GPRIdx]});
618     break;
619   default:
620     return getInvalidInstructionMapping();
621   }
622 
623   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
624                                NumOperands);
625 }
626 
627 using InstListTy = GISelWorkList<4>;
628 namespace {
629 class InstManager : public GISelChangeObserver {
630   InstListTy &InstList;
631 
632 public:
633   InstManager(InstListTy &Insts) : InstList(Insts) {}
634 
635   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
636   void erasingInstr(MachineInstr &MI) override {}
637   void changingInstr(MachineInstr &MI) override {}
638   void changedInstr(MachineInstr &MI) override {}
639 };
640 } // end anonymous namespace
641 
642 /// Here we have to narrowScalar s64 operands to s32, combine away
643 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
644 /// We manually assign 32 bit gprb to register operands of all new instructions
645 /// that got created in the process since they will not end up in RegBankSelect
646 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
647 void MipsRegisterBankInfo::applyMappingImpl(
648     const OperandsMapper &OpdMapper) const {
649   MachineInstr &MI = OpdMapper.getMI();
650   InstListTy NewInstrs;
651   MachineIRBuilder B(MI);
652   MachineFunction *MF = MI.getMF();
653   MachineRegisterInfo &MRI = OpdMapper.getMRI();
654 
655   InstManager NewInstrObserver(NewInstrs);
656   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
657   LegalizerHelper Helper(*MF, WrapperObserver, B);
658   LegalizationArtifactCombiner ArtCombiner(
659       B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
660 
661   switch (MI.getOpcode()) {
662   case TargetOpcode::G_LOAD:
663   case TargetOpcode::G_STORE:
664   case TargetOpcode::G_PHI:
665   case TargetOpcode::G_SELECT:
666   case TargetOpcode::G_IMPLICIT_DEF: {
667     Helper.narrowScalar(MI, 0, LLT::scalar(32));
668     // Handle new instructions.
669     while (!NewInstrs.empty()) {
670       MachineInstr *NewMI = NewInstrs.pop_back_val();
671       // This is new G_UNMERGE that was created during narrowScalar and will
672       // not be considered for regbank selection. RegBankSelect for mips
673       // visits/makes corresponding G_MERGE first. Combine them here.
674       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
675         SmallVector<MachineInstr *, 2> DeadInstrs;
676         ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
677         for (MachineInstr *DeadMI : DeadInstrs)
678           DeadMI->eraseFromParent();
679       }
680       // This G_MERGE will be combined away when its corresponding G_UNMERGE
681       // gets regBankSelected.
682       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
683         continue;
684       else
685         // Manually set register banks for all register operands to 32 bit gprb.
686         for (auto Op : NewMI->operands()) {
687           if (Op.isReg()) {
688             assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
689                    "Only 32 bit gprb is handled here.\n");
690             MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
691           }
692         }
693     }
694     return;
695   }
696   case TargetOpcode::G_UNMERGE_VALUES: {
697     SmallVector<MachineInstr *, 2> DeadInstrs;
698     ArtCombiner.tryCombineMerges(MI, DeadInstrs);
699     for (MachineInstr *DeadMI : DeadInstrs)
700       DeadMI->eraseFromParent();
701     return;
702   }
703   default:
704     break;
705   }
706 
707   return applyDefaultMapping(OpdMapper);
708 }
709