xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===- ARMRegisterBankInfo.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 ARM.
100b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ARMRegisterBankInfo.h"
140b57cec5SDimitry Andric #include "ARMInstrInfo.h" // For the register classes
150b57cec5SDimitry Andric #include "ARMSubtarget.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #define GET_TARGET_REGBANK_IMPL
220b57cec5SDimitry Andric #include "ARMGenRegisterBank.inc"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric // FIXME: TableGen this.
270b57cec5SDimitry Andric // If it grows too much and TableGen still isn't ready to do the job, extract it
280b57cec5SDimitry Andric // into an ARMGenRegisterBankInfo.def (similar to AArch64).
290b57cec5SDimitry Andric namespace llvm {
300b57cec5SDimitry Andric namespace ARM {
310b57cec5SDimitry Andric enum PartialMappingIdx {
320b57cec5SDimitry Andric   PMI_GPR,
330b57cec5SDimitry Andric   PMI_SPR,
340b57cec5SDimitry Andric   PMI_DPR,
350b57cec5SDimitry Andric   PMI_Min = PMI_GPR,
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{
390b57cec5SDimitry Andric     // GPR Partial Mapping
400b57cec5SDimitry Andric     {0, 32, GPRRegBank},
410b57cec5SDimitry Andric     // SPR Partial Mapping
420b57cec5SDimitry Andric     {0, 32, FPRRegBank},
430b57cec5SDimitry Andric     // DPR Partial Mapping
440b57cec5SDimitry Andric     {0, 64, FPRRegBank},
450b57cec5SDimitry Andric };
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #ifndef NDEBUG
480b57cec5SDimitry Andric static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,
490b57cec5SDimitry Andric                              unsigned Start, unsigned Length,
500b57cec5SDimitry Andric                              unsigned RegBankID) {
510b57cec5SDimitry Andric   return PM.StartIdx == Start && PM.Length == Length &&
520b57cec5SDimitry Andric          PM.RegBank->getID() == RegBankID;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric static void checkPartialMappings() {
560b57cec5SDimitry Andric   assert(
570b57cec5SDimitry Andric       checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
580b57cec5SDimitry Andric       "Wrong mapping for GPR");
590b57cec5SDimitry Andric   assert(
600b57cec5SDimitry Andric       checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
610b57cec5SDimitry Andric       "Wrong mapping for SPR");
620b57cec5SDimitry Andric   assert(
630b57cec5SDimitry Andric       checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
640b57cec5SDimitry Andric       "Wrong mapping for DPR");
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric #endif
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric enum ValueMappingIdx {
690b57cec5SDimitry Andric   InvalidIdx = 0,
700b57cec5SDimitry Andric   GPR3OpsIdx = 1,
710b57cec5SDimitry Andric   SPR3OpsIdx = 4,
720b57cec5SDimitry Andric   DPR3OpsIdx = 7,
730b57cec5SDimitry Andric };
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = {
760b57cec5SDimitry Andric     // invalid
770b57cec5SDimitry Andric     {nullptr, 0},
780b57cec5SDimitry Andric     // 3 ops in GPRs
790b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
800b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
810b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
820b57cec5SDimitry Andric     // 3 ops in SPRs
830b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
840b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
850b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
860b57cec5SDimitry Andric     // 3 ops in DPRs
870b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
880b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
890b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1}};
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric #ifndef NDEBUG
920b57cec5SDimitry Andric static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
930b57cec5SDimitry Andric                               RegisterBankInfo::PartialMapping *BreakDown) {
940b57cec5SDimitry Andric   return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric static void checkValueMappings() {
980b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
990b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1000b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1010b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
1020b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1030b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1040b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
1050b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1060b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
1090b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1100b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1110b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
1120b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1130b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1140b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
1150b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1160b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
1190b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1200b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1210b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
1220b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1230b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1240b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
1250b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1260b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric #endif
1290b57cec5SDimitry Andric } // end namespace arm
1300b57cec5SDimitry Andric } // end namespace llvm
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
1330b57cec5SDimitry Andric     : ARMGenRegisterBankInfo() {
1340b57cec5SDimitry Andric   // We have only one set of register banks, whatever the subtarget
1350b57cec5SDimitry Andric   // is. Therefore, the initialization of the RegBanks table should be
1360b57cec5SDimitry Andric   // done only once. Indeed the table of all register banks
1370b57cec5SDimitry Andric   // (ARM::RegBanks) is unique in the compiler. At some point, it
1380b57cec5SDimitry Andric   // will get tablegen'ed and the whole constructor becomes empty.
1395ffd83dbSDimitry Andric   static llvm::once_flag InitializeRegisterBankFlag;
1400b57cec5SDimitry Andric 
1415ffd83dbSDimitry Andric   static auto InitializeRegisterBankOnce = [&]() {
1420b57cec5SDimitry Andric     const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
1430b57cec5SDimitry Andric     (void)RBGPR;
1440b57cec5SDimitry Andric     assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric     // Initialize the GPR bank.
1470b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
1480b57cec5SDimitry Andric            "Subclass not added?");
1490b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
1500b57cec5SDimitry Andric            "Subclass not added?");
1510b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
1520b57cec5SDimitry Andric            "Subclass not added?");
1530b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
1540b57cec5SDimitry Andric            "Subclass not added?");
1550b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
1560b57cec5SDimitry Andric            "Subclass not added?");
1570b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
1580b57cec5SDimitry Andric            "Subclass not added?");
159*e8d8bef9SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnoip_and_tcGPRRegClassID)) &&
1600b57cec5SDimitry Andric            "Subclass not added?");
161*e8d8bef9SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(
162*e8d8bef9SDimitry Andric                ARM::tGPREven_and_GPRnoip_and_tcGPRRegClassID)) &&
1630b57cec5SDimitry Andric            "Subclass not added?");
1640b57cec5SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&
1650b57cec5SDimitry Andric            "Subclass not added?");
1660b57cec5SDimitry Andric     assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric #ifndef NDEBUG
1690b57cec5SDimitry Andric     ARM::checkPartialMappings();
1700b57cec5SDimitry Andric     ARM::checkValueMappings();
1710b57cec5SDimitry Andric #endif
1725ffd83dbSDimitry Andric   };
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric   llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
177480093f4SDimitry Andric const RegisterBank &
178480093f4SDimitry Andric ARMRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
179480093f4SDimitry Andric                                             LLT) const {
1800b57cec5SDimitry Andric   using namespace ARM;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   switch (RC.getID()) {
1830b57cec5SDimitry Andric   case GPRRegClassID:
1840b57cec5SDimitry Andric   case GPRwithAPSRRegClassID:
185*e8d8bef9SDimitry Andric   case GPRnoipRegClassID:
1860b57cec5SDimitry Andric   case GPRnopcRegClassID:
187*e8d8bef9SDimitry Andric   case GPRnoip_and_GPRnopcRegClassID:
1880b57cec5SDimitry Andric   case rGPRRegClassID:
1890b57cec5SDimitry Andric   case GPRspRegClassID:
190*e8d8bef9SDimitry Andric   case GPRnoip_and_tcGPRRegClassID:
1910b57cec5SDimitry Andric   case tcGPRRegClassID:
1920b57cec5SDimitry Andric   case tGPRRegClassID:
1930b57cec5SDimitry Andric   case tGPREvenRegClassID:
1940b57cec5SDimitry Andric   case tGPROddRegClassID:
1950b57cec5SDimitry Andric   case tGPR_and_tGPREvenRegClassID:
1960b57cec5SDimitry Andric   case tGPR_and_tGPROddRegClassID:
1970b57cec5SDimitry Andric   case tGPREven_and_tcGPRRegClassID:
198*e8d8bef9SDimitry Andric   case tGPREven_and_GPRnoip_and_tcGPRRegClassID:
1990b57cec5SDimitry Andric   case tGPROdd_and_tcGPRRegClassID:
2000b57cec5SDimitry Andric     return getRegBank(ARM::GPRRegBankID);
2010b57cec5SDimitry Andric   case HPRRegClassID:
2020b57cec5SDimitry Andric   case SPR_8RegClassID:
2030b57cec5SDimitry Andric   case SPRRegClassID:
2040b57cec5SDimitry Andric   case DPR_8RegClassID:
2050b57cec5SDimitry Andric   case DPRRegClassID:
2060b57cec5SDimitry Andric   case QPRRegClassID:
2070b57cec5SDimitry Andric     return getRegBank(ARM::FPRRegBankID);
2080b57cec5SDimitry Andric   default:
2090b57cec5SDimitry Andric     llvm_unreachable("Unsupported register kind");
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   llvm_unreachable("Switch should handle all register classes");
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &
2160b57cec5SDimitry Andric ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
2170b57cec5SDimitry Andric   auto Opc = MI.getOpcode();
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   // Try the default logic for non-generic instructions that are either copies
2200b57cec5SDimitry Andric   // or already have some operands assigned to banks.
2210b57cec5SDimitry Andric   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
2220b57cec5SDimitry Andric     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
2230b57cec5SDimitry Andric     if (Mapping.isValid())
2240b57cec5SDimitry Andric       return Mapping;
2250b57cec5SDimitry Andric   }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   using namespace TargetOpcode;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
2300b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2310b57cec5SDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2320b57cec5SDimitry Andric   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   switch (Opc) {
2350b57cec5SDimitry Andric   case G_ADD:
2360b57cec5SDimitry Andric   case G_SUB: {
2370b57cec5SDimitry Andric     // Integer operations where the source and destination are in the
2380b57cec5SDimitry Andric     // same register class.
2390b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2400b57cec5SDimitry Andric     OperandsMapping = Ty.getSizeInBits() == 64
2410b57cec5SDimitry Andric                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
2420b57cec5SDimitry Andric                           : &ARM::ValueMappings[ARM::GPR3OpsIdx];
2430b57cec5SDimitry Andric     break;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric   case G_MUL:
2460b57cec5SDimitry Andric   case G_AND:
2470b57cec5SDimitry Andric   case G_OR:
2480b57cec5SDimitry Andric   case G_XOR:
2490b57cec5SDimitry Andric   case G_LSHR:
2500b57cec5SDimitry Andric   case G_ASHR:
2510b57cec5SDimitry Andric   case G_SHL:
2520b57cec5SDimitry Andric   case G_SDIV:
2530b57cec5SDimitry Andric   case G_UDIV:
2540b57cec5SDimitry Andric   case G_SEXT:
2550b57cec5SDimitry Andric   case G_ZEXT:
2560b57cec5SDimitry Andric   case G_ANYEXT:
257480093f4SDimitry Andric   case G_PTR_ADD:
2580b57cec5SDimitry Andric   case G_INTTOPTR:
2590b57cec5SDimitry Andric   case G_PTRTOINT:
2600b57cec5SDimitry Andric   case G_CTLZ:
2610b57cec5SDimitry Andric     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
2620b57cec5SDimitry Andric     // the real world we would use different mappings.
2630b57cec5SDimitry Andric     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
2640b57cec5SDimitry Andric     break;
2650b57cec5SDimitry Andric   case G_TRUNC: {
2660b57cec5SDimitry Andric     // In some cases we may end up with a G_TRUNC from a 64-bit value to a
2670b57cec5SDimitry Andric     // 32-bit value. This isn't a real floating point trunc (that would be a
2680b57cec5SDimitry Andric     // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
2690b57cec5SDimitry Andric     // because the legalizer doesn't distinguish between integer and floating
2700b57cec5SDimitry Andric     // point values so it may leave some 64-bit integers un-narrowed. Until we
2710b57cec5SDimitry Andric     // have a more principled solution that doesn't let such things sneak all
2720b57cec5SDimitry Andric     // the way to this point, just map the source to a DPR and the destination
2730b57cec5SDimitry Andric     // to a GPR.
2740b57cec5SDimitry Andric     LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
2750b57cec5SDimitry Andric     OperandsMapping =
2760b57cec5SDimitry Andric         LargeTy.getSizeInBits() <= 32
2770b57cec5SDimitry Andric             ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
2780b57cec5SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
2790b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]});
2800b57cec5SDimitry Andric     break;
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric   case G_LOAD:
2830b57cec5SDimitry Andric   case G_STORE: {
2840b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2850b57cec5SDimitry Andric     OperandsMapping =
2860b57cec5SDimitry Andric         Ty.getSizeInBits() == 64
2870b57cec5SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
2880b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
2890b57cec5SDimitry Andric             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric   case G_FADD:
2930b57cec5SDimitry Andric   case G_FSUB:
2940b57cec5SDimitry Andric   case G_FMUL:
2950b57cec5SDimitry Andric   case G_FDIV:
2960b57cec5SDimitry Andric   case G_FNEG: {
2970b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2980b57cec5SDimitry Andric     OperandsMapping =Ty.getSizeInBits() == 64
2990b57cec5SDimitry Andric                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
3000b57cec5SDimitry Andric                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
3010b57cec5SDimitry Andric     break;
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric   case G_FMA: {
3040b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3050b57cec5SDimitry Andric     OperandsMapping =
3060b57cec5SDimitry Andric         Ty.getSizeInBits() == 64
3070b57cec5SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3080b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
3090b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
3100b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]})
3110b57cec5SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3120b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
3130b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
3140b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3150b57cec5SDimitry Andric     break;
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric   case G_FPEXT: {
3180b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3190b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3200b57cec5SDimitry Andric     if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
3210b57cec5SDimitry Andric       OperandsMapping =
3220b57cec5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3230b57cec5SDimitry Andric                               &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3240b57cec5SDimitry Andric     break;
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric   case G_FPTRUNC: {
3270b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3280b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3290b57cec5SDimitry Andric     if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
3300b57cec5SDimitry Andric       OperandsMapping =
3310b57cec5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3320b57cec5SDimitry Andric                               &ARM::ValueMappings[ARM::DPR3OpsIdx]});
3330b57cec5SDimitry Andric     break;
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric   case G_FPTOSI:
3360b57cec5SDimitry Andric   case G_FPTOUI: {
3370b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3380b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3390b57cec5SDimitry Andric     if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
3400b57cec5SDimitry Andric         ToTy.getSizeInBits() == 32)
3410b57cec5SDimitry Andric       OperandsMapping =
3420b57cec5SDimitry Andric           FromTy.getSizeInBits() == 64
3430b57cec5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3440b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::DPR3OpsIdx]})
3450b57cec5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3460b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3470b57cec5SDimitry Andric     break;
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric   case G_SITOFP:
3500b57cec5SDimitry Andric   case G_UITOFP: {
3510b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3520b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3530b57cec5SDimitry Andric     if (FromTy.getSizeInBits() == 32 &&
3540b57cec5SDimitry Andric         (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
3550b57cec5SDimitry Andric       OperandsMapping =
3560b57cec5SDimitry Andric           ToTy.getSizeInBits() == 64
3570b57cec5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3580b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]})
3590b57cec5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3600b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3610b57cec5SDimitry Andric     break;
3620b57cec5SDimitry Andric   }
3630b57cec5SDimitry Andric   case G_FCONSTANT: {
3640b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3650b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping(
3660b57cec5SDimitry Andric         {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
3670b57cec5SDimitry Andric                                   : &ARM::ValueMappings[ARM::SPR3OpsIdx],
3680b57cec5SDimitry Andric          nullptr});
3690b57cec5SDimitry Andric     break;
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric   case G_CONSTANT:
3720b57cec5SDimitry Andric   case G_FRAME_INDEX:
3730b57cec5SDimitry Andric   case G_GLOBAL_VALUE:
3740b57cec5SDimitry Andric     OperandsMapping =
3750b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
3760b57cec5SDimitry Andric     break;
3770b57cec5SDimitry Andric   case G_SELECT: {
3780b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3790b57cec5SDimitry Andric     (void)Ty;
3800b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
3810b57cec5SDimitry Andric     (void)Ty2;
3820b57cec5SDimitry Andric     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
3830b57cec5SDimitry Andric     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
3840b57cec5SDimitry Andric     OperandsMapping =
3850b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3860b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3870b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3880b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3890b57cec5SDimitry Andric     break;
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   case G_ICMP: {
3920b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
3930b57cec5SDimitry Andric     (void)Ty2;
3940b57cec5SDimitry Andric     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
3950b57cec5SDimitry Andric     OperandsMapping =
3960b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
3970b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3980b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3990b57cec5SDimitry Andric     break;
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric   case G_FCMP: {
4020b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4030b57cec5SDimitry Andric     (void)Ty;
4040b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
4050b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
4060b57cec5SDimitry Andric     (void)Ty2;
4070b57cec5SDimitry Andric     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
4080b57cec5SDimitry Andric     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
4090b57cec5SDimitry Andric            "Mismatched operand sizes for G_FCMP");
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     unsigned Size = Ty1.getSizeInBits();
4120b57cec5SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
4150b57cec5SDimitry Andric                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
4160b57cec5SDimitry Andric     OperandsMapping =
4170b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
4180b57cec5SDimitry Andric                             FPRValueMapping, FPRValueMapping});
4190b57cec5SDimitry Andric     break;
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric   case G_MERGE_VALUES: {
4220b57cec5SDimitry Andric     // We only support G_MERGE_VALUES for creating a double precision floating
4230b57cec5SDimitry Andric     // point value out of two GPRs.
4240b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4250b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
4260b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
4270b57cec5SDimitry Andric     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
4280b57cec5SDimitry Andric         Ty2.getSizeInBits() != 32)
4290b57cec5SDimitry Andric       return getInvalidInstructionMapping();
4300b57cec5SDimitry Andric     OperandsMapping =
4310b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
4320b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
4330b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
4340b57cec5SDimitry Andric     break;
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric   case G_UNMERGE_VALUES: {
4370b57cec5SDimitry Andric     // We only support G_UNMERGE_VALUES for splitting a double precision
4380b57cec5SDimitry Andric     // floating point value into two GPRs.
4390b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4400b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
4410b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
4420b57cec5SDimitry Andric     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
4430b57cec5SDimitry Andric         Ty2.getSizeInBits() != 64)
4440b57cec5SDimitry Andric       return getInvalidInstructionMapping();
4450b57cec5SDimitry Andric     OperandsMapping =
4460b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
4470b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
4480b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
4490b57cec5SDimitry Andric     break;
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric   case G_BR:
4520b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({nullptr});
4530b57cec5SDimitry Andric     break;
4540b57cec5SDimitry Andric   case G_BRCOND:
4550b57cec5SDimitry Andric     OperandsMapping =
4560b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
4570b57cec5SDimitry Andric     break;
4580b57cec5SDimitry Andric   case DBG_VALUE: {
4590b57cec5SDimitry Andric     SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
4600b57cec5SDimitry Andric     const MachineOperand &MaybeReg = MI.getOperand(0);
4610b57cec5SDimitry Andric     if (MaybeReg.isReg() && MaybeReg.getReg()) {
4620b57cec5SDimitry Andric       unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
4630b57cec5SDimitry Andric       if (Size > 32 && Size != 64)
4640b57cec5SDimitry Andric         return getInvalidInstructionMapping();
4650b57cec5SDimitry Andric       OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
4660b57cec5SDimitry Andric                                    : &ARM::ValueMappings[ARM::GPR3OpsIdx];
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping(OperandBanks);
4690b57cec5SDimitry Andric     break;
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric   default:
4720b57cec5SDimitry Andric     return getInvalidInstructionMapping();
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric #ifndef NDEBUG
4760b57cec5SDimitry Andric   for (unsigned i = 0; i < NumOperands; i++) {
4770b57cec5SDimitry Andric     for (const auto &Mapping : OperandsMapping[i]) {
4780b57cec5SDimitry Andric       assert(
4790b57cec5SDimitry Andric           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
4800b57cec5SDimitry Andric            MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&
4810b57cec5SDimitry Andric           "Trying to use floating point register bank on target without vfp");
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric #endif
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
4870b57cec5SDimitry Andric                                NumOperands);
4880b57cec5SDimitry Andric }
489