xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for Mips.
100b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MipsRegisterBankInfo.h"
140b57cec5SDimitry Andric #include "MipsInstrInfo.h"
158bcb0991SDimitry Andric #include "MipsTargetMachine.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #define GET_TARGET_REGBANK_IMPL
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "MipsGenRegisterBank.inc"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric namespace Mips {
270b57cec5SDimitry Andric enum PartialMappingIdx {
280b57cec5SDimitry Andric   PMI_GPR,
290b57cec5SDimitry Andric   PMI_SPR,
300b57cec5SDimitry Andric   PMI_DPR,
318bcb0991SDimitry Andric   PMI_MSA,
320b57cec5SDimitry Andric   PMI_Min = PMI_GPR,
330b57cec5SDimitry Andric };
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{
360b57cec5SDimitry Andric     {0, 32, GPRBRegBank},
370b57cec5SDimitry Andric     {0, 32, FPRBRegBank},
388bcb0991SDimitry Andric     {0, 64, FPRBRegBank},
398bcb0991SDimitry Andric     {0, 128, FPRBRegBank}
400b57cec5SDimitry Andric };
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric enum ValueMappingIdx {
430b57cec5SDimitry Andric     InvalidIdx = 0,
440b57cec5SDimitry Andric     GPRIdx = 1,
450b57cec5SDimitry Andric     SPRIdx = 4,
468bcb0991SDimitry Andric     DPRIdx = 7,
478bcb0991SDimitry Andric     MSAIdx = 10
480b57cec5SDimitry Andric };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = {
510b57cec5SDimitry Andric     // invalid
520b57cec5SDimitry Andric     {nullptr, 0},
530b57cec5SDimitry Andric     // up to 3 operands in GPRs
540b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
550b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
560b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
578bcb0991SDimitry Andric     // up to 3 operands in FPRs - single precission
580b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
590b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
600b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
618bcb0991SDimitry Andric     // up to 3 operands in FPRs - double precission
620b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
630b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
648bcb0991SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
658bcb0991SDimitry Andric     // up to 3 operands in FPRs - MSA
668bcb0991SDimitry Andric     {&PartMappings[PMI_MSA - PMI_Min], 1},
678bcb0991SDimitry Andric     {&PartMappings[PMI_MSA - PMI_Min], 1},
688bcb0991SDimitry Andric     {&PartMappings[PMI_MSA - PMI_Min], 1}
690b57cec5SDimitry Andric };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric } // end namespace Mips
720b57cec5SDimitry Andric } // end namespace llvm
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric using namespace llvm;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
770b57cec5SDimitry Andric     : MipsGenRegisterBankInfo() {}
780b57cec5SDimitry Andric 
79480093f4SDimitry Andric const RegisterBank &
80480093f4SDimitry Andric MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
81480093f4SDimitry Andric                                              LLT) const {
820b57cec5SDimitry Andric   using namespace Mips;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   switch (RC.getID()) {
850b57cec5SDimitry Andric   case Mips::GPR32RegClassID:
860b57cec5SDimitry Andric   case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
870b57cec5SDimitry Andric   case Mips::GPRMM16MovePPairFirstRegClassID:
880b57cec5SDimitry Andric   case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
890b57cec5SDimitry Andric   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
900b57cec5SDimitry Andric   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
910b57cec5SDimitry Andric   case Mips::SP32RegClassID:
920b57cec5SDimitry Andric   case Mips::GP32RegClassID:
930b57cec5SDimitry Andric     return getRegBank(Mips::GPRBRegBankID);
940b57cec5SDimitry Andric   case Mips::FGRCCRegClassID:
950b57cec5SDimitry Andric   case Mips::FGR32RegClassID:
960b57cec5SDimitry Andric   case Mips::FGR64RegClassID:
970b57cec5SDimitry Andric   case Mips::AFGR64RegClassID:
988bcb0991SDimitry Andric   case Mips::MSA128BRegClassID:
998bcb0991SDimitry Andric   case Mips::MSA128HRegClassID:
1008bcb0991SDimitry Andric   case Mips::MSA128WRegClassID:
1018bcb0991SDimitry Andric   case Mips::MSA128DRegClassID:
1020b57cec5SDimitry Andric     return getRegBank(Mips::FPRBRegBankID);
1030b57cec5SDimitry Andric   default:
1040b57cec5SDimitry Andric     llvm_unreachable("Register class not supported");
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric // Instructions where all register operands are floating point.
1090b57cec5SDimitry Andric static bool isFloatingPointOpcode(unsigned Opc) {
1100b57cec5SDimitry Andric   switch (Opc) {
1110b57cec5SDimitry Andric   case TargetOpcode::G_FCONSTANT:
1120b57cec5SDimitry Andric   case TargetOpcode::G_FADD:
1130b57cec5SDimitry Andric   case TargetOpcode::G_FSUB:
1140b57cec5SDimitry Andric   case TargetOpcode::G_FMUL:
1150b57cec5SDimitry Andric   case TargetOpcode::G_FDIV:
1160b57cec5SDimitry Andric   case TargetOpcode::G_FABS:
1170b57cec5SDimitry Andric   case TargetOpcode::G_FSQRT:
1180b57cec5SDimitry Andric   case TargetOpcode::G_FCEIL:
1190b57cec5SDimitry Andric   case TargetOpcode::G_FFLOOR:
1200b57cec5SDimitry Andric   case TargetOpcode::G_FPEXT:
1210b57cec5SDimitry Andric   case TargetOpcode::G_FPTRUNC:
1220b57cec5SDimitry Andric     return true;
1230b57cec5SDimitry Andric   default:
1240b57cec5SDimitry Andric     return false;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric // Instructions where use operands are floating point registers.
1290b57cec5SDimitry Andric // Def operands are general purpose.
1300b57cec5SDimitry Andric static bool isFloatingPointOpcodeUse(unsigned Opc) {
1310b57cec5SDimitry Andric   switch (Opc) {
1320b57cec5SDimitry Andric   case TargetOpcode::G_FPTOSI:
1330b57cec5SDimitry Andric   case TargetOpcode::G_FPTOUI:
1340b57cec5SDimitry Andric   case TargetOpcode::G_FCMP:
1350b57cec5SDimitry Andric     return true;
1360b57cec5SDimitry Andric   default:
1370b57cec5SDimitry Andric     return isFloatingPointOpcode(Opc);
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric // Instructions where def operands are floating point registers.
1420b57cec5SDimitry Andric // Use operands are general purpose.
1430b57cec5SDimitry Andric static bool isFloatingPointOpcodeDef(unsigned Opc) {
1440b57cec5SDimitry Andric   switch (Opc) {
1450b57cec5SDimitry Andric   case TargetOpcode::G_SITOFP:
1460b57cec5SDimitry Andric   case TargetOpcode::G_UITOFP:
1470b57cec5SDimitry Andric     return true;
1480b57cec5SDimitry Andric   default:
1490b57cec5SDimitry Andric     return isFloatingPointOpcode(Opc);
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
153*5ffd83dbSDimitry Andric static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
154*5ffd83dbSDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_LOAD ||
155*5ffd83dbSDimitry Andric       MI->getOpcode() == TargetOpcode::G_STORE) {
156*5ffd83dbSDimitry Andric     auto MMO = *MI->memoperands_begin();
157*5ffd83dbSDimitry Andric     const MipsSubtarget &STI =
158*5ffd83dbSDimitry Andric         static_cast<const MipsSubtarget &>(MI->getMF()->getSubtarget());
159*5ffd83dbSDimitry Andric     if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
160*5ffd83dbSDimitry Andric                                 MMO->getAlign() < MMO->getSize()))
161*5ffd83dbSDimitry Andric       return true;
162*5ffd83dbSDimitry Andric   }
163*5ffd83dbSDimitry Andric   return false;
164*5ffd83dbSDimitry Andric }
165*5ffd83dbSDimitry Andric 
1660b57cec5SDimitry Andric static bool isAmbiguous(unsigned Opc) {
1670b57cec5SDimitry Andric   switch (Opc) {
1680b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
1690b57cec5SDimitry Andric   case TargetOpcode::G_STORE:
1700b57cec5SDimitry Andric   case TargetOpcode::G_PHI:
1710b57cec5SDimitry Andric   case TargetOpcode::G_SELECT:
1728bcb0991SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF:
173*5ffd83dbSDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES:
174*5ffd83dbSDimitry Andric   case TargetOpcode::G_MERGE_VALUES:
1750b57cec5SDimitry Andric     return true;
1760b57cec5SDimitry Andric   default:
1770b57cec5SDimitry Andric     return false;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
1820b57cec5SDimitry Andric     Register Reg, const MachineRegisterInfo &MRI) {
1830b57cec5SDimitry Andric   assert(!MRI.getType(Reg).isPointer() &&
1840b57cec5SDimitry Andric          "Pointers are gprb, they should not be considered as ambiguous.\n");
1850b57cec5SDimitry Andric   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
1860b57cec5SDimitry Andric     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
1870b57cec5SDimitry Andric     // Copy with many uses.
1880b57cec5SDimitry Andric     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
1898bcb0991SDimitry Andric         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
1900b57cec5SDimitry Andric       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
1910b57cec5SDimitry Andric     else
1920b57cec5SDimitry Andric       DefUses.push_back(skipCopiesOutgoing(&UseMI));
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
1970b57cec5SDimitry Andric     Register Reg, const MachineRegisterInfo &MRI) {
1980b57cec5SDimitry Andric   assert(!MRI.getType(Reg).isPointer() &&
1990b57cec5SDimitry Andric          "Pointers are gprb, they should not be considered as ambiguous.\n");
2000b57cec5SDimitry Andric   MachineInstr *DefMI = MRI.getVRegDef(Reg);
2010b57cec5SDimitry Andric   UseDefs.push_back(skipCopiesIncoming(DefMI));
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric MachineInstr *
2050b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
2060b57cec5SDimitry Andric     MachineInstr *MI) const {
2070b57cec5SDimitry Andric   const MachineFunction &MF = *MI->getParent()->getParent();
2080b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2090b57cec5SDimitry Andric   MachineInstr *Ret = MI;
2100b57cec5SDimitry Andric   while (Ret->getOpcode() == TargetOpcode::COPY &&
2118bcb0991SDimitry Andric          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
2120b57cec5SDimitry Andric          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
2130b57cec5SDimitry Andric     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric   return Ret;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric MachineInstr *
2190b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
2200b57cec5SDimitry Andric     MachineInstr *MI) const {
2210b57cec5SDimitry Andric   const MachineFunction &MF = *MI->getParent()->getParent();
2220b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2230b57cec5SDimitry Andric   MachineInstr *Ret = MI;
2240b57cec5SDimitry Andric   while (Ret->getOpcode() == TargetOpcode::COPY &&
2258bcb0991SDimitry Andric          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
2260b57cec5SDimitry Andric     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
2270b57cec5SDimitry Andric   return Ret;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
2310b57cec5SDimitry Andric     const MachineInstr *MI) {
2320b57cec5SDimitry Andric   assert(isAmbiguous(MI->getOpcode()) &&
2330b57cec5SDimitry Andric          "Not implemented for non Ambiguous opcode.\n");
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_LOAD)
2380b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_STORE)
2410b57cec5SDimitry Andric     addUseDef(MI->getOperand(0).getReg(), MRI);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_PHI) {
2440b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
2470b57cec5SDimitry Andric       addUseDef(MI->getOperand(i).getReg(), MRI);
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
2510b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric     addUseDef(MI->getOperand(2).getReg(), MRI);
2540b57cec5SDimitry Andric     addUseDef(MI->getOperand(3).getReg(), MRI);
2550b57cec5SDimitry Andric   }
2568bcb0991SDimitry Andric 
2578bcb0991SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2588bcb0991SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
259*5ffd83dbSDimitry Andric 
260*5ffd83dbSDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
261*5ffd83dbSDimitry Andric     addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
262*5ffd83dbSDimitry Andric 
263*5ffd83dbSDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
264*5ffd83dbSDimitry Andric       addDefUses(MI->getOperand(0).getReg(), MRI);
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visit(
268*5ffd83dbSDimitry Andric     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
269*5ffd83dbSDimitry Andric     InstType &AmbiguousTy) {
2700b57cec5SDimitry Andric   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
2710b57cec5SDimitry Andric   if (wasVisited(MI))
2720b57cec5SDimitry Andric     return true; // InstType has already been determined for MI.
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   startVisit(MI);
2750b57cec5SDimitry Andric   AmbiguousRegDefUseContainer DefUseContainer(MI);
2760b57cec5SDimitry Andric 
277*5ffd83dbSDimitry Andric   if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
278*5ffd83dbSDimitry Andric     setTypes(MI, Integer);
279*5ffd83dbSDimitry Andric     return true;
280*5ffd83dbSDimitry Andric   }
281*5ffd83dbSDimitry Andric 
282*5ffd83dbSDimitry Andric   if (AmbiguousTy == InstType::Ambiguous &&
283*5ffd83dbSDimitry Andric       (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
284*5ffd83dbSDimitry Andric        MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
285*5ffd83dbSDimitry Andric     AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
286*5ffd83dbSDimitry Andric 
2870b57cec5SDimitry Andric   // Visit instructions where MI's DEF operands are USED.
288*5ffd83dbSDimitry Andric   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
2890b57cec5SDimitry Andric     return true;
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   // Visit instructions that DEFINE MI's USE operands.
292*5ffd83dbSDimitry Andric   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
2930b57cec5SDimitry Andric     return true;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   // All MI's adjacent instructions, are ambiguous.
2960b57cec5SDimitry Andric   if (!WaitingForTypeOfMI) {
2970b57cec5SDimitry Andric     // This is chain of ambiguous instructions.
298*5ffd83dbSDimitry Andric     setTypes(MI, AmbiguousTy);
2990b57cec5SDimitry Andric     return true;
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
3020b57cec5SDimitry Andric   // instructions or has no other adjacent instructions. Anyway InstType could
3030b57cec5SDimitry Andric   // not be determined. There could be unexplored path from some of
3040b57cec5SDimitry Andric   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
3050b57cec5SDimitry Andric   // mapping available.
3060b57cec5SDimitry Andric   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
3070b57cec5SDimitry Andric   // this way when WaitingForTypeOfMI figures out its InstType same InstType
3080b57cec5SDimitry Andric   // will be assigned to all instructions in this branch.
3090b57cec5SDimitry Andric   addToWaitingQueue(WaitingForTypeOfMI, MI);
3100b57cec5SDimitry Andric   return false;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
3140b57cec5SDimitry Andric     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
315*5ffd83dbSDimitry Andric     bool isDefUse, InstType &AmbiguousTy) {
3160b57cec5SDimitry Andric   while (!AdjacentInstrs.empty()) {
3170b57cec5SDimitry Andric     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
3200b57cec5SDimitry Andric                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
3210b57cec5SDimitry Andric       setTypes(MI, InstType::FloatingPoint);
3220b57cec5SDimitry Andric       return true;
3230b57cec5SDimitry Andric     }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     // Determine InstType from register bank of phys register that is
3260b57cec5SDimitry Andric     // 'isDefUse ? def : use' of this copy.
3270b57cec5SDimitry Andric     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
3280b57cec5SDimitry Andric       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
3290b57cec5SDimitry Andric       return true;
3300b57cec5SDimitry Andric     }
3310b57cec5SDimitry Andric 
332*5ffd83dbSDimitry Andric     // Defaults to integer instruction. Small registers in G_MERGE (uses) and
333*5ffd83dbSDimitry Andric     // G_UNMERGE (defs) will always be gprb.
334*5ffd83dbSDimitry Andric     if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
335*5ffd83dbSDimitry Andric         (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
336*5ffd83dbSDimitry Andric         !isAmbiguous(AdjMI->getOpcode())) {
3370b57cec5SDimitry Andric       setTypes(MI, InstType::Integer);
3380b57cec5SDimitry Andric       return true;
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     // When AdjMI was visited first, MI has to continue to explore remaining
3420b57cec5SDimitry Andric     // adjacent instructions and determine InstType without visiting AdjMI.
3430b57cec5SDimitry Andric     if (!wasVisited(AdjMI) ||
3440b57cec5SDimitry Andric         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
345*5ffd83dbSDimitry Andric       if (visit(AdjMI, MI, AmbiguousTy)) {
3460b57cec5SDimitry Andric         // InstType is successfully determined and is same as for AdjMI.
3470b57cec5SDimitry Andric         setTypes(MI, getRecordedTypeForInstr(AdjMI));
3480b57cec5SDimitry Andric         return true;
3490b57cec5SDimitry Andric       }
3500b57cec5SDimitry Andric     }
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric   return false;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
3560b57cec5SDimitry Andric                                                    InstType InstTy) {
3570b57cec5SDimitry Andric   changeRecordedTypeForInstr(MI, InstTy);
3580b57cec5SDimitry Andric   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
3590b57cec5SDimitry Andric     setTypes(WaitingInstr, InstTy);
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
3640b57cec5SDimitry Andric     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
3658bcb0991SDimitry Andric   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
3660b57cec5SDimitry Andric          "Copies of non physical registers should not be considered here.\n");
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   const MachineFunction &MF = *CopyInst->getMF();
3690b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
3700b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
3710b57cec5SDimitry Andric   const RegisterBankInfo &RBI =
3720b57cec5SDimitry Andric       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
3730b57cec5SDimitry Andric   const RegisterBank *Bank =
3740b57cec5SDimitry Andric       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   if (Bank == &Mips::FPRBRegBank)
3770b57cec5SDimitry Andric     setTypes(MI, InstType::FloatingPoint);
3780b57cec5SDimitry Andric   else if (Bank == &Mips::GPRBRegBank)
3790b57cec5SDimitry Andric     setTypes(MI, InstType::Integer);
3800b57cec5SDimitry Andric   else
3810b57cec5SDimitry Andric     llvm_unreachable("Unsupported register bank.\n");
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric MipsRegisterBankInfo::InstType
3850b57cec5SDimitry Andric MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
386*5ffd83dbSDimitry Andric   InstType DefaultAmbiguousType = InstType::Ambiguous;
387*5ffd83dbSDimitry Andric   visit(MI, nullptr, DefaultAmbiguousType);
3880b57cec5SDimitry Andric   return getRecordedTypeForInstr(MI);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
3920b57cec5SDimitry Andric     llvm::StringRef FunctionName) {
3930b57cec5SDimitry Andric   if (MFName != FunctionName) {
394*5ffd83dbSDimitry Andric     MFName = std::string(FunctionName);
3950b57cec5SDimitry Andric     WaitingQueues.clear();
3960b57cec5SDimitry Andric     Types.clear();
3970b57cec5SDimitry Andric   }
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric 
4008bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *
4018bcb0991SDimitry Andric getMSAMapping(const MachineFunction &MF) {
4028bcb0991SDimitry Andric   assert(static_cast<const MipsSubtarget &>(MF.getSubtarget()).hasMSA() &&
4038bcb0991SDimitry Andric          "MSA mapping not available on target without MSA.");
4048bcb0991SDimitry Andric   return &Mips::ValueMappings[Mips::MSAIdx];
4058bcb0991SDimitry Andric }
4068bcb0991SDimitry Andric 
4078bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
4088bcb0991SDimitry Andric   return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
4098bcb0991SDimitry Andric                     : &Mips::ValueMappings[Mips::DPRIdx];
4108bcb0991SDimitry Andric }
4118bcb0991SDimitry Andric 
4128bcb0991SDimitry Andric static const unsigned CustomMappingID = 1;
4138bcb0991SDimitry Andric 
4148bcb0991SDimitry Andric // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
4158bcb0991SDimitry Andric // will be split into two 32 bit registers in gprb.
4168bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *
4178bcb0991SDimitry Andric getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
4188bcb0991SDimitry Andric   if (Size == 32)
4198bcb0991SDimitry Andric     return &Mips::ValueMappings[Mips::GPRIdx];
4208bcb0991SDimitry Andric 
4218bcb0991SDimitry Andric   MappingID = CustomMappingID;
4228bcb0991SDimitry Andric   return &Mips::ValueMappings[Mips::DPRIdx];
4238bcb0991SDimitry Andric }
4248bcb0991SDimitry Andric 
4250b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &
4260b57cec5SDimitry Andric MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   static TypeInfoForMF TI;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   // Reset TI internal data when MF changes.
4310b57cec5SDimitry Andric   TI.cleanupIfNewFunction(MI.getMF()->getName());
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
4340b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
4350b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   if (MI.getOpcode() != TargetOpcode::G_PHI) {
4380b57cec5SDimitry Andric     const RegisterBankInfo::InstructionMapping &Mapping =
4390b57cec5SDimitry Andric         getInstrMappingImpl(MI);
4400b57cec5SDimitry Andric     if (Mapping.isValid())
4410b57cec5SDimitry Andric       return Mapping;
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   using namespace TargetOpcode;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   unsigned NumOperands = MI.getNumOperands();
4470b57cec5SDimitry Andric   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4480b57cec5SDimitry Andric   unsigned MappingID = DefaultMappingID;
4498bcb0991SDimitry Andric 
4508bcb0991SDimitry Andric   // Check if LLT sizes match sizes of available register banks.
4518bcb0991SDimitry Andric   for (const MachineOperand &Op : MI.operands()) {
4528bcb0991SDimitry Andric     if (Op.isReg()) {
4538bcb0991SDimitry Andric       LLT RegTy = MRI.getType(Op.getReg());
4548bcb0991SDimitry Andric 
4558bcb0991SDimitry Andric       if (RegTy.isScalar() &&
4568bcb0991SDimitry Andric           (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
4578bcb0991SDimitry Andric         return getInvalidInstructionMapping();
4588bcb0991SDimitry Andric 
4598bcb0991SDimitry Andric       if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
4608bcb0991SDimitry Andric         return getInvalidInstructionMapping();
4618bcb0991SDimitry Andric     }
4628bcb0991SDimitry Andric   }
4638bcb0991SDimitry Andric 
4648bcb0991SDimitry Andric   const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
4658bcb0991SDimitry Andric   unsigned Op0Size = Op0Ty.getSizeInBits();
4668bcb0991SDimitry Andric   InstType InstTy = InstType::Integer;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   switch (Opc) {
4690b57cec5SDimitry Andric   case G_TRUNC:
4700b57cec5SDimitry Andric   case G_UMULH:
4710b57cec5SDimitry Andric   case G_ZEXTLOAD:
4720b57cec5SDimitry Andric   case G_SEXTLOAD:
473480093f4SDimitry Andric   case G_PTR_ADD:
4748bcb0991SDimitry Andric   case G_INTTOPTR:
4758bcb0991SDimitry Andric   case G_PTRTOINT:
4760b57cec5SDimitry Andric   case G_AND:
4770b57cec5SDimitry Andric   case G_OR:
4780b57cec5SDimitry Andric   case G_XOR:
4790b57cec5SDimitry Andric   case G_SHL:
4800b57cec5SDimitry Andric   case G_ASHR:
4810b57cec5SDimitry Andric   case G_LSHR:
4828bcb0991SDimitry Andric   case G_BRINDIRECT:
4838bcb0991SDimitry Andric   case G_VASTART:
484480093f4SDimitry Andric   case G_BSWAP:
485*5ffd83dbSDimitry Andric   case G_CTLZ:
4860b57cec5SDimitry Andric     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4870b57cec5SDimitry Andric     break;
4888bcb0991SDimitry Andric   case G_ADD:
489480093f4SDimitry Andric   case G_SUB:
490480093f4SDimitry Andric   case G_MUL:
491480093f4SDimitry Andric   case G_SDIV:
492480093f4SDimitry Andric   case G_SREM:
493480093f4SDimitry Andric   case G_UDIV:
494480093f4SDimitry Andric   case G_UREM:
4958bcb0991SDimitry Andric     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4968bcb0991SDimitry Andric     if (Op0Size == 128)
4978bcb0991SDimitry Andric       OperandsMapping = getMSAMapping(MF);
4988bcb0991SDimitry Andric     break;
4998bcb0991SDimitry Andric   case G_STORE:
500*5ffd83dbSDimitry Andric   case G_LOAD: {
5018bcb0991SDimitry Andric     if (Op0Size == 128) {
5028bcb0991SDimitry Andric       OperandsMapping = getOperandsMapping(
5038bcb0991SDimitry Andric           {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
5048bcb0991SDimitry Andric       break;
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric 
5078bcb0991SDimitry Andric     if (!Op0Ty.isPointer())
5088bcb0991SDimitry Andric       InstTy = TI.determineInstType(&MI);
5098bcb0991SDimitry Andric 
510*5ffd83dbSDimitry Andric     if (isFloatingPoint_32or64(InstTy, Op0Size) ||
511*5ffd83dbSDimitry Andric         isAmbiguous_64(InstTy, Op0Size)) {
5128bcb0991SDimitry Andric       OperandsMapping = getOperandsMapping(
5138bcb0991SDimitry Andric           {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
514*5ffd83dbSDimitry Andric     } else {
515*5ffd83dbSDimitry Andric       assert((isInteger_32(InstTy, Op0Size) ||
516*5ffd83dbSDimitry Andric               isAmbiguous_32(InstTy, Op0Size) ||
517*5ffd83dbSDimitry Andric               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
518*5ffd83dbSDimitry Andric              "Unexpected Inst type");
5190b57cec5SDimitry Andric       OperandsMapping =
5208bcb0991SDimitry Andric           getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
5210b57cec5SDimitry Andric                               &Mips::ValueMappings[Mips::GPRIdx]});
522*5ffd83dbSDimitry Andric     }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     break;
525*5ffd83dbSDimitry Andric   }
526*5ffd83dbSDimitry Andric   case G_PHI: {
5278bcb0991SDimitry Andric     if (!Op0Ty.isPointer())
5280b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric     // PHI is copylike and should have one regbank in mapping for def register.
531*5ffd83dbSDimitry Andric     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
5320b57cec5SDimitry Andric       OperandsMapping =
5330b57cec5SDimitry Andric           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
534*5ffd83dbSDimitry Andric       TI.clearTypeInfoData(&MI);
5350b57cec5SDimitry Andric       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
5360b57cec5SDimitry Andric                                    /*NumOperands=*/1);
5370b57cec5SDimitry Andric     }
538*5ffd83dbSDimitry Andric     assert((isInteger_32(InstTy, Op0Size) ||
539*5ffd83dbSDimitry Andric             isFloatingPoint_32or64(InstTy, Op0Size) ||
540*5ffd83dbSDimitry Andric             isAmbiguous_32or64(InstTy, Op0Size)) &&
541*5ffd83dbSDimitry Andric            "Unexpected Inst type");
5420b57cec5SDimitry Andric     // Use default handling for PHI, i.e. set reg bank of def operand to match
5430b57cec5SDimitry Andric     // register banks of use operands.
5448bcb0991SDimitry Andric     return getInstrMappingImpl(MI);
545*5ffd83dbSDimitry Andric   }
5460b57cec5SDimitry Andric   case G_SELECT: {
5478bcb0991SDimitry Andric     if (!Op0Ty.isPointer())
5480b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
549*5ffd83dbSDimitry Andric     if (isFloatingPoint_32or64(InstTy, Op0Size) ||
550*5ffd83dbSDimitry Andric         isAmbiguous_64(InstTy, Op0Size)) {
5518bcb0991SDimitry Andric       const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
5520b57cec5SDimitry Andric       OperandsMapping = getOperandsMapping(
5530b57cec5SDimitry Andric           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
5540b57cec5SDimitry Andric       break;
5558bcb0991SDimitry Andric     } else {
556*5ffd83dbSDimitry Andric       assert((isInteger_32(InstTy, Op0Size) ||
557*5ffd83dbSDimitry Andric               isAmbiguous_32(InstTy, Op0Size) ||
558*5ffd83dbSDimitry Andric               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
559*5ffd83dbSDimitry Andric              "Unexpected Inst type");
5600b57cec5SDimitry Andric       const RegisterBankInfo::ValueMapping *Bank =
5618bcb0991SDimitry Andric           getGprbOrCustomMapping(Op0Size, MappingID);
5620b57cec5SDimitry Andric       OperandsMapping = getOperandsMapping(
5630b57cec5SDimitry Andric           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
5640b57cec5SDimitry Andric     }
5650b57cec5SDimitry Andric     break;
5660b57cec5SDimitry Andric   }
567*5ffd83dbSDimitry Andric   case G_IMPLICIT_DEF: {
5688bcb0991SDimitry Andric     if (!Op0Ty.isPointer())
5698bcb0991SDimitry Andric       InstTy = TI.determineInstType(&MI);
5708bcb0991SDimitry Andric 
571*5ffd83dbSDimitry Andric     if (isFloatingPoint_32or64(InstTy, Op0Size))
5728bcb0991SDimitry Andric       OperandsMapping = getFprbMapping(Op0Size);
573*5ffd83dbSDimitry Andric     else {
574*5ffd83dbSDimitry Andric       assert((isInteger_32(InstTy, Op0Size) ||
575*5ffd83dbSDimitry Andric               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
576*5ffd83dbSDimitry Andric              "Unexpected Inst type");
5778bcb0991SDimitry Andric       OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
578*5ffd83dbSDimitry Andric     }
579*5ffd83dbSDimitry Andric   } break;
580*5ffd83dbSDimitry Andric   case G_UNMERGE_VALUES: {
581*5ffd83dbSDimitry Andric     assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
582*5ffd83dbSDimitry Andric     unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
583*5ffd83dbSDimitry Andric     InstTy = TI.determineInstType(&MI);
584*5ffd83dbSDimitry Andric     assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
585*5ffd83dbSDimitry Andric             isFloatingPoint_64(InstTy, Op3Size)) &&
586*5ffd83dbSDimitry Andric            "Unexpected Inst type");
5870b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
5880b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx],
5890b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::DPRIdx]});
590*5ffd83dbSDimitry Andric     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
5910b57cec5SDimitry Andric       MappingID = CustomMappingID;
5920b57cec5SDimitry Andric     break;
593*5ffd83dbSDimitry Andric   }
594*5ffd83dbSDimitry Andric   case G_MERGE_VALUES: {
595*5ffd83dbSDimitry Andric     InstTy = TI.determineInstType(&MI);
596*5ffd83dbSDimitry Andric     assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
597*5ffd83dbSDimitry Andric             isFloatingPoint_64(InstTy, Op0Size)) &&
598*5ffd83dbSDimitry Andric            "Unexpected Inst type");
5990b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
6000b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx],
6010b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx]});
602*5ffd83dbSDimitry Andric     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
6030b57cec5SDimitry Andric       MappingID = CustomMappingID;
6040b57cec5SDimitry Andric     break;
605*5ffd83dbSDimitry Andric   }
6060b57cec5SDimitry Andric   case G_FADD:
6070b57cec5SDimitry Andric   case G_FSUB:
6080b57cec5SDimitry Andric   case G_FMUL:
6090b57cec5SDimitry Andric   case G_FDIV:
6100b57cec5SDimitry Andric   case G_FABS:
6118bcb0991SDimitry Andric   case G_FSQRT:
6128bcb0991SDimitry Andric     OperandsMapping = getFprbMapping(Op0Size);
613480093f4SDimitry Andric     if (Op0Size == 128)
614480093f4SDimitry Andric       OperandsMapping = getMSAMapping(MF);
6150b57cec5SDimitry Andric     break;
6168bcb0991SDimitry Andric   case G_FCONSTANT:
6178bcb0991SDimitry Andric     OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
6180b57cec5SDimitry Andric     break;
6190b57cec5SDimitry Andric   case G_FCMP: {
6208bcb0991SDimitry Andric     unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
6210b57cec5SDimitry Andric     OperandsMapping =
6220b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6238bcb0991SDimitry Andric                             getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
6240b57cec5SDimitry Andric     break;
6250b57cec5SDimitry Andric   }
6260b57cec5SDimitry Andric   case G_FPEXT:
6270b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
6280b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::SPRIdx]});
6290b57cec5SDimitry Andric     break;
6300b57cec5SDimitry Andric   case G_FPTRUNC:
6310b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
6320b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::DPRIdx]});
6330b57cec5SDimitry Andric     break;
6340b57cec5SDimitry Andric   case G_FPTOSI: {
6358bcb0991SDimitry Andric     assert((Op0Size == 32) && "Unsupported integer size");
6360b57cec5SDimitry Andric     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
6378bcb0991SDimitry Andric     OperandsMapping = getOperandsMapping(
6388bcb0991SDimitry Andric         {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
6398bcb0991SDimitry Andric     break;
6408bcb0991SDimitry Andric   }
6418bcb0991SDimitry Andric   case G_SITOFP:
6428bcb0991SDimitry Andric     assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
6430b57cec5SDimitry Andric            "Unsupported integer size");
6448bcb0991SDimitry Andric     OperandsMapping = getOperandsMapping(
6458bcb0991SDimitry Andric         {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
6460b57cec5SDimitry Andric     break;
6470b57cec5SDimitry Andric   case G_CONSTANT:
6480b57cec5SDimitry Andric   case G_FRAME_INDEX:
6490b57cec5SDimitry Andric   case G_GLOBAL_VALUE:
6508bcb0991SDimitry Andric   case G_JUMP_TABLE:
6510b57cec5SDimitry Andric   case G_BRCOND:
6520b57cec5SDimitry Andric     OperandsMapping =
6530b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
6540b57cec5SDimitry Andric     break;
6558bcb0991SDimitry Andric   case G_BRJT:
6568bcb0991SDimitry Andric     OperandsMapping =
6578bcb0991SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6588bcb0991SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx]});
6598bcb0991SDimitry Andric     break;
6600b57cec5SDimitry Andric   case G_ICMP:
6610b57cec5SDimitry Andric     OperandsMapping =
6620b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6630b57cec5SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx],
6640b57cec5SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx]});
6650b57cec5SDimitry Andric     break;
6660b57cec5SDimitry Andric   default:
6670b57cec5SDimitry Andric     return getInvalidInstructionMapping();
6680b57cec5SDimitry Andric   }
6690b57cec5SDimitry Andric 
670*5ffd83dbSDimitry Andric   if (MappingID == CustomMappingID)
671*5ffd83dbSDimitry Andric     TI.clearTypeInfoData(&MI);
6720b57cec5SDimitry Andric   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
6730b57cec5SDimitry Andric                                NumOperands);
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric using InstListTy = GISelWorkList<4>;
6770b57cec5SDimitry Andric namespace {
6780b57cec5SDimitry Andric class InstManager : public GISelChangeObserver {
6790b57cec5SDimitry Andric   InstListTy &InstList;
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric public:
6820b57cec5SDimitry Andric   InstManager(InstListTy &Insts) : InstList(Insts) {}
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
6850b57cec5SDimitry Andric   void erasingInstr(MachineInstr &MI) override {}
6860b57cec5SDimitry Andric   void changingInstr(MachineInstr &MI) override {}
6870b57cec5SDimitry Andric   void changedInstr(MachineInstr &MI) override {}
6880b57cec5SDimitry Andric };
6890b57cec5SDimitry Andric } // end anonymous namespace
6900b57cec5SDimitry Andric 
6918bcb0991SDimitry Andric void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
6928bcb0991SDimitry Andric                                       MachineRegisterInfo &MRI) const {
6938bcb0991SDimitry Andric   Register Dest = MI.getOperand(0).getReg();
6948bcb0991SDimitry Andric   switch (MI.getOpcode()) {
6958bcb0991SDimitry Andric   case TargetOpcode::G_STORE:
6968bcb0991SDimitry Andric     // No def operands, skip this instruction.
6978bcb0991SDimitry Andric     break;
6988bcb0991SDimitry Andric   case TargetOpcode::G_CONSTANT:
6998bcb0991SDimitry Andric   case TargetOpcode::G_LOAD:
7008bcb0991SDimitry Andric   case TargetOpcode::G_SELECT:
7018bcb0991SDimitry Andric   case TargetOpcode::G_PHI:
7028bcb0991SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF: {
7038bcb0991SDimitry Andric     assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
7048bcb0991SDimitry Andric     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
7058bcb0991SDimitry Andric     break;
7068bcb0991SDimitry Andric   }
707480093f4SDimitry Andric   case TargetOpcode::G_PTR_ADD: {
7088bcb0991SDimitry Andric     assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
7098bcb0991SDimitry Andric     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
7108bcb0991SDimitry Andric     break;
7118bcb0991SDimitry Andric   }
7128bcb0991SDimitry Andric   default:
7138bcb0991SDimitry Andric     llvm_unreachable("Unexpected opcode.");
7148bcb0991SDimitry Andric   }
7158bcb0991SDimitry Andric }
7168bcb0991SDimitry Andric 
7178bcb0991SDimitry Andric static void
7188bcb0991SDimitry Andric combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
719*5ffd83dbSDimitry Andric                             MachineInstr &MI, GISelObserverWrapper &Observer) {
720480093f4SDimitry Andric   SmallVector<Register, 4> UpdatedDefs;
7218bcb0991SDimitry Andric   SmallVector<MachineInstr *, 2> DeadInstrs;
722*5ffd83dbSDimitry Andric   ArtCombiner.tryCombineMerges(MI, DeadInstrs, UpdatedDefs, Observer);
7238bcb0991SDimitry Andric   for (MachineInstr *DeadMI : DeadInstrs)
7248bcb0991SDimitry Andric     DeadMI->eraseFromParent();
7258bcb0991SDimitry Andric }
7268bcb0991SDimitry Andric 
7270b57cec5SDimitry Andric void MipsRegisterBankInfo::applyMappingImpl(
7280b57cec5SDimitry Andric     const OperandsMapper &OpdMapper) const {
7290b57cec5SDimitry Andric   MachineInstr &MI = OpdMapper.getMI();
7300b57cec5SDimitry Andric   InstListTy NewInstrs;
7310b57cec5SDimitry Andric   MachineIRBuilder B(MI);
7320b57cec5SDimitry Andric   MachineFunction *MF = MI.getMF();
7330b57cec5SDimitry Andric   MachineRegisterInfo &MRI = OpdMapper.getMRI();
7348bcb0991SDimitry Andric   const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   InstManager NewInstrObserver(NewInstrs);
7370b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
7380b57cec5SDimitry Andric   LegalizerHelper Helper(*MF, WrapperObserver, B);
7398bcb0991SDimitry Andric   LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   switch (MI.getOpcode()) {
7420b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
7430b57cec5SDimitry Andric   case TargetOpcode::G_STORE:
7440b57cec5SDimitry Andric   case TargetOpcode::G_PHI:
7458bcb0991SDimitry Andric   case TargetOpcode::G_SELECT:
7468bcb0991SDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF: {
7470b57cec5SDimitry Andric     Helper.narrowScalar(MI, 0, LLT::scalar(32));
7480b57cec5SDimitry Andric     // Handle new instructions.
7490b57cec5SDimitry Andric     while (!NewInstrs.empty()) {
7500b57cec5SDimitry Andric       MachineInstr *NewMI = NewInstrs.pop_back_val();
7510b57cec5SDimitry Andric       // This is new G_UNMERGE that was created during narrowScalar and will
7520b57cec5SDimitry Andric       // not be considered for regbank selection. RegBankSelect for mips
7530b57cec5SDimitry Andric       // visits/makes corresponding G_MERGE first. Combine them here.
7548bcb0991SDimitry Andric       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
755*5ffd83dbSDimitry Andric         combineAwayG_UNMERGE_VALUES(ArtCombiner, *NewMI, WrapperObserver);
7560b57cec5SDimitry Andric       // This G_MERGE will be combined away when its corresponding G_UNMERGE
7570b57cec5SDimitry Andric       // gets regBankSelected.
7580b57cec5SDimitry Andric       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
7590b57cec5SDimitry Andric         continue;
7600b57cec5SDimitry Andric       else
7618bcb0991SDimitry Andric         // Manually set register banks for def operands to 32 bit gprb.
7628bcb0991SDimitry Andric         setRegBank(*NewMI, MRI);
7630b57cec5SDimitry Andric     }
7640b57cec5SDimitry Andric     return;
7650b57cec5SDimitry Andric   }
7668bcb0991SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES:
767*5ffd83dbSDimitry Andric     combineAwayG_UNMERGE_VALUES(ArtCombiner, MI, WrapperObserver);
7680b57cec5SDimitry Andric     return;
7690b57cec5SDimitry Andric   default:
7700b57cec5SDimitry Andric     break;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   return applyDefaultMapping(OpdMapper);
7740b57cec5SDimitry Andric }
775