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