xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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/MachineRegisterInfo.h"
1781ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBank.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.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 
38*5f757f3fSDimitry Andric const 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 
75*5f757f3fSDimitry Andric const 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
92*5f757f3fSDimitry Andric static bool
93*5f757f3fSDimitry Andric checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
94*5f757f3fSDimitry Andric                   const RegisterBankInfo::PartialMapping *BreakDown) {
950b57cec5SDimitry Andric   return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric static void checkValueMappings() {
990b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
1000b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1010b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1020b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
1030b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1040b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1050b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
1060b57cec5SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1070b57cec5SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
1100b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1110b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1120b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
1130b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1140b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1150b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
1160b57cec5SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1170b57cec5SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
1200b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1210b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1220b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
1230b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1240b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1250b57cec5SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
1260b57cec5SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1270b57cec5SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric #endif
1300b57cec5SDimitry Andric } // end namespace arm
1310b57cec5SDimitry Andric } // end namespace llvm
1320b57cec5SDimitry Andric 
13381ad6265SDimitry Andric ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) {
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?");
159e8d8bef9SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnoip_and_tcGPRRegClassID)) &&
1600b57cec5SDimitry Andric            "Subclass not added?");
161e8d8bef9SDimitry Andric     assert(RBGPR.covers(*TRI.getRegClass(
162e8d8bef9SDimitry 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?");
16606c3fb27SDimitry Andric     assert(getMaximumSize(RBGPR.getID()) == 32 &&
16706c3fb27SDimitry Andric            "GPRs should hold up to 32-bit");
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric #ifndef NDEBUG
1700b57cec5SDimitry Andric     ARM::checkPartialMappings();
1710b57cec5SDimitry Andric     ARM::checkValueMappings();
1720b57cec5SDimitry Andric #endif
1735ffd83dbSDimitry Andric   };
1745ffd83dbSDimitry Andric 
1755ffd83dbSDimitry Andric   llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
178480093f4SDimitry Andric const RegisterBank &
179480093f4SDimitry Andric ARMRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
180480093f4SDimitry Andric                                             LLT) const {
1810b57cec5SDimitry Andric   using namespace ARM;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   switch (RC.getID()) {
1840b57cec5SDimitry Andric   case GPRRegClassID:
1850b57cec5SDimitry Andric   case GPRwithAPSRRegClassID:
186e8d8bef9SDimitry Andric   case GPRnoipRegClassID:
1870b57cec5SDimitry Andric   case GPRnopcRegClassID:
188e8d8bef9SDimitry Andric   case GPRnoip_and_GPRnopcRegClassID:
1890b57cec5SDimitry Andric   case rGPRRegClassID:
1900b57cec5SDimitry Andric   case GPRspRegClassID:
191e8d8bef9SDimitry Andric   case GPRnoip_and_tcGPRRegClassID:
1920b57cec5SDimitry Andric   case tcGPRRegClassID:
1930b57cec5SDimitry Andric   case tGPRRegClassID:
1940b57cec5SDimitry Andric   case tGPREvenRegClassID:
1950b57cec5SDimitry Andric   case tGPROddRegClassID:
1960b57cec5SDimitry Andric   case tGPR_and_tGPREvenRegClassID:
1970b57cec5SDimitry Andric   case tGPR_and_tGPROddRegClassID:
1980b57cec5SDimitry Andric   case tGPREven_and_tcGPRRegClassID:
199e8d8bef9SDimitry Andric   case tGPREven_and_GPRnoip_and_tcGPRRegClassID:
2000b57cec5SDimitry Andric   case tGPROdd_and_tcGPRRegClassID:
2010b57cec5SDimitry Andric     return getRegBank(ARM::GPRRegBankID);
2020b57cec5SDimitry Andric   case HPRRegClassID:
2030b57cec5SDimitry Andric   case SPR_8RegClassID:
2040b57cec5SDimitry Andric   case SPRRegClassID:
2050b57cec5SDimitry Andric   case DPR_8RegClassID:
2060b57cec5SDimitry Andric   case DPRRegClassID:
2070b57cec5SDimitry Andric   case QPRRegClassID:
2080b57cec5SDimitry Andric     return getRegBank(ARM::FPRRegBankID);
2090b57cec5SDimitry Andric   default:
2100b57cec5SDimitry Andric     llvm_unreachable("Unsupported register kind");
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   llvm_unreachable("Switch should handle all register classes");
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &
2170b57cec5SDimitry Andric ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
2180b57cec5SDimitry Andric   auto Opc = MI.getOpcode();
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   // Try the default logic for non-generic instructions that are either copies
2210b57cec5SDimitry Andric   // or already have some operands assigned to banks.
2220b57cec5SDimitry Andric   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
2230b57cec5SDimitry Andric     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
2240b57cec5SDimitry Andric     if (Mapping.isValid())
2250b57cec5SDimitry Andric       return Mapping;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   using namespace TargetOpcode;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
2310b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2320b57cec5SDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2330b57cec5SDimitry Andric   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   switch (Opc) {
2360b57cec5SDimitry Andric   case G_ADD:
2370b57cec5SDimitry Andric   case G_SUB: {
2380b57cec5SDimitry Andric     // Integer operations where the source and destination are in the
2390b57cec5SDimitry Andric     // same register class.
2400b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2410b57cec5SDimitry Andric     OperandsMapping = Ty.getSizeInBits() == 64
2420b57cec5SDimitry Andric                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
2430b57cec5SDimitry Andric                           : &ARM::ValueMappings[ARM::GPR3OpsIdx];
2440b57cec5SDimitry Andric     break;
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   case G_MUL:
2470b57cec5SDimitry Andric   case G_AND:
2480b57cec5SDimitry Andric   case G_OR:
2490b57cec5SDimitry Andric   case G_XOR:
2500b57cec5SDimitry Andric   case G_LSHR:
2510b57cec5SDimitry Andric   case G_ASHR:
2520b57cec5SDimitry Andric   case G_SHL:
2530b57cec5SDimitry Andric   case G_SDIV:
2540b57cec5SDimitry Andric   case G_UDIV:
2550b57cec5SDimitry Andric   case G_SEXT:
2560b57cec5SDimitry Andric   case G_ZEXT:
2570b57cec5SDimitry Andric   case G_ANYEXT:
258480093f4SDimitry Andric   case G_PTR_ADD:
2590b57cec5SDimitry Andric   case G_INTTOPTR:
2600b57cec5SDimitry Andric   case G_PTRTOINT:
2610b57cec5SDimitry Andric   case G_CTLZ:
2620b57cec5SDimitry Andric     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
2630b57cec5SDimitry Andric     // the real world we would use different mappings.
2640b57cec5SDimitry Andric     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
2650b57cec5SDimitry Andric     break;
2660b57cec5SDimitry Andric   case G_TRUNC: {
2670b57cec5SDimitry Andric     // In some cases we may end up with a G_TRUNC from a 64-bit value to a
2680b57cec5SDimitry Andric     // 32-bit value. This isn't a real floating point trunc (that would be a
2690b57cec5SDimitry Andric     // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
2700b57cec5SDimitry Andric     // because the legalizer doesn't distinguish between integer and floating
2710b57cec5SDimitry Andric     // point values so it may leave some 64-bit integers un-narrowed. Until we
2720b57cec5SDimitry Andric     // have a more principled solution that doesn't let such things sneak all
2730b57cec5SDimitry Andric     // the way to this point, just map the source to a DPR and the destination
2740b57cec5SDimitry Andric     // to a GPR.
2750b57cec5SDimitry Andric     LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
2760b57cec5SDimitry Andric     OperandsMapping =
2770b57cec5SDimitry Andric         LargeTy.getSizeInBits() <= 32
2780b57cec5SDimitry Andric             ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
2790b57cec5SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
2800b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]});
2810b57cec5SDimitry Andric     break;
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric   case G_LOAD:
2840b57cec5SDimitry Andric   case G_STORE: {
2850b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2860b57cec5SDimitry Andric     OperandsMapping =
2870b57cec5SDimitry Andric         Ty.getSizeInBits() == 64
2880b57cec5SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
2890b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
2900b57cec5SDimitry Andric             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
2910b57cec5SDimitry Andric     break;
2920b57cec5SDimitry Andric   }
2930b57cec5SDimitry Andric   case G_FADD:
2940b57cec5SDimitry Andric   case G_FSUB:
2950b57cec5SDimitry Andric   case G_FMUL:
2960b57cec5SDimitry Andric   case G_FDIV:
2970b57cec5SDimitry Andric   case G_FNEG: {
2980b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2990b57cec5SDimitry Andric     OperandsMapping =Ty.getSizeInBits() == 64
3000b57cec5SDimitry Andric                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
3010b57cec5SDimitry Andric                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
3020b57cec5SDimitry Andric     break;
3030b57cec5SDimitry Andric   }
3040b57cec5SDimitry Andric   case G_FMA: {
3050b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3060b57cec5SDimitry Andric     OperandsMapping =
3070b57cec5SDimitry Andric         Ty.getSizeInBits() == 64
3080b57cec5SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3090b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
3100b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
3110b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]})
3120b57cec5SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3130b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
3140b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
3150b57cec5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3160b57cec5SDimitry Andric     break;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric   case G_FPEXT: {
3190b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3200b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3210b57cec5SDimitry Andric     if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
3220b57cec5SDimitry Andric       OperandsMapping =
3230b57cec5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3240b57cec5SDimitry Andric                               &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3250b57cec5SDimitry Andric     break;
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric   case G_FPTRUNC: {
3280b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3290b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3300b57cec5SDimitry Andric     if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
3310b57cec5SDimitry Andric       OperandsMapping =
3320b57cec5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3330b57cec5SDimitry Andric                               &ARM::ValueMappings[ARM::DPR3OpsIdx]});
3340b57cec5SDimitry Andric     break;
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric   case G_FPTOSI:
3370b57cec5SDimitry Andric   case G_FPTOUI: {
3380b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3390b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3400b57cec5SDimitry Andric     if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
3410b57cec5SDimitry Andric         ToTy.getSizeInBits() == 32)
3420b57cec5SDimitry Andric       OperandsMapping =
3430b57cec5SDimitry Andric           FromTy.getSizeInBits() == 64
3440b57cec5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3450b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::DPR3OpsIdx]})
3460b57cec5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3470b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3480b57cec5SDimitry Andric     break;
3490b57cec5SDimitry Andric   }
3500b57cec5SDimitry Andric   case G_SITOFP:
3510b57cec5SDimitry Andric   case G_UITOFP: {
3520b57cec5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3530b57cec5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3540b57cec5SDimitry Andric     if (FromTy.getSizeInBits() == 32 &&
3550b57cec5SDimitry Andric         (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
3560b57cec5SDimitry Andric       OperandsMapping =
3570b57cec5SDimitry Andric           ToTy.getSizeInBits() == 64
3580b57cec5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3590b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]})
3600b57cec5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3610b57cec5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3620b57cec5SDimitry Andric     break;
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric   case G_FCONSTANT: {
3650b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3660b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping(
3670b57cec5SDimitry Andric         {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
3680b57cec5SDimitry Andric                                   : &ARM::ValueMappings[ARM::SPR3OpsIdx],
3690b57cec5SDimitry Andric          nullptr});
3700b57cec5SDimitry Andric     break;
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric   case G_CONSTANT:
3730b57cec5SDimitry Andric   case G_FRAME_INDEX:
3740b57cec5SDimitry Andric   case G_GLOBAL_VALUE:
3750b57cec5SDimitry Andric     OperandsMapping =
3760b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
3770b57cec5SDimitry Andric     break;
3780b57cec5SDimitry Andric   case G_SELECT: {
3790b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3800b57cec5SDimitry Andric     (void)Ty;
3810b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
3820b57cec5SDimitry Andric     (void)Ty2;
3830b57cec5SDimitry Andric     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
3840b57cec5SDimitry Andric     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
3850b57cec5SDimitry Andric     OperandsMapping =
3860b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3870b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3880b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3890b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3900b57cec5SDimitry Andric     break;
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric   case G_ICMP: {
3930b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
3940b57cec5SDimitry Andric     (void)Ty2;
3950b57cec5SDimitry Andric     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
3960b57cec5SDimitry Andric     OperandsMapping =
3970b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
3980b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
3990b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
4000b57cec5SDimitry Andric     break;
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric   case G_FCMP: {
4030b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4040b57cec5SDimitry Andric     (void)Ty;
4050b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
4060b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
4070b57cec5SDimitry Andric     (void)Ty2;
4080b57cec5SDimitry Andric     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
4090b57cec5SDimitry Andric     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
4100b57cec5SDimitry Andric            "Mismatched operand sizes for G_FCMP");
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric     unsigned Size = Ty1.getSizeInBits();
4130b57cec5SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
4160b57cec5SDimitry Andric                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
4170b57cec5SDimitry Andric     OperandsMapping =
4180b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
4190b57cec5SDimitry Andric                             FPRValueMapping, FPRValueMapping});
4200b57cec5SDimitry Andric     break;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric   case G_MERGE_VALUES: {
4230b57cec5SDimitry Andric     // We only support G_MERGE_VALUES for creating a double precision floating
4240b57cec5SDimitry Andric     // point value out of two GPRs.
4250b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4260b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
4270b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
4280b57cec5SDimitry Andric     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
4290b57cec5SDimitry Andric         Ty2.getSizeInBits() != 32)
4300b57cec5SDimitry Andric       return getInvalidInstructionMapping();
4310b57cec5SDimitry Andric     OperandsMapping =
4320b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
4330b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
4340b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
4350b57cec5SDimitry Andric     break;
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric   case G_UNMERGE_VALUES: {
4380b57cec5SDimitry Andric     // We only support G_UNMERGE_VALUES for splitting a double precision
4390b57cec5SDimitry Andric     // floating point value into two GPRs.
4400b57cec5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4410b57cec5SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
4420b57cec5SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
4430b57cec5SDimitry Andric     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
4440b57cec5SDimitry Andric         Ty2.getSizeInBits() != 64)
4450b57cec5SDimitry Andric       return getInvalidInstructionMapping();
4460b57cec5SDimitry Andric     OperandsMapping =
4470b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
4480b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
4490b57cec5SDimitry Andric                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
4500b57cec5SDimitry Andric     break;
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   case G_BR:
4530b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({nullptr});
4540b57cec5SDimitry Andric     break;
4550b57cec5SDimitry Andric   case G_BRCOND:
4560b57cec5SDimitry Andric     OperandsMapping =
4570b57cec5SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
4580b57cec5SDimitry Andric     break;
4590b57cec5SDimitry Andric   case DBG_VALUE: {
4600b57cec5SDimitry Andric     SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
4610b57cec5SDimitry Andric     const MachineOperand &MaybeReg = MI.getOperand(0);
4620b57cec5SDimitry Andric     if (MaybeReg.isReg() && MaybeReg.getReg()) {
4630b57cec5SDimitry Andric       unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
4640b57cec5SDimitry Andric       if (Size > 32 && Size != 64)
4650b57cec5SDimitry Andric         return getInvalidInstructionMapping();
4660b57cec5SDimitry Andric       OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
4670b57cec5SDimitry Andric                                    : &ARM::ValueMappings[ARM::GPR3OpsIdx];
4680b57cec5SDimitry Andric     }
4690b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping(OperandBanks);
4700b57cec5SDimitry Andric     break;
4710b57cec5SDimitry Andric   }
4720b57cec5SDimitry Andric   default:
4730b57cec5SDimitry Andric     return getInvalidInstructionMapping();
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric #ifndef NDEBUG
4770b57cec5SDimitry Andric   for (unsigned i = 0; i < NumOperands; i++) {
4780b57cec5SDimitry Andric     for (const auto &Mapping : OperandsMapping[i]) {
4790b57cec5SDimitry Andric       assert(
4800b57cec5SDimitry Andric           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
4810b57cec5SDimitry Andric            MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&
4820b57cec5SDimitry Andric           "Trying to use floating point register bank on target without vfp");
4830b57cec5SDimitry Andric     }
4840b57cec5SDimitry Andric   }
4850b57cec5SDimitry Andric #endif
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
4880b57cec5SDimitry Andric                                NumOperands);
4890b57cec5SDimitry Andric }
490