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