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