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
checkPartMapping(const RegisterBankInfo::PartialMapping & PM,unsigned Start,unsigned Length,unsigned RegBankID)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
checkPartialMappings()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
checkValueMapping(const RegisterBankInfo::ValueMapping & VM,const RegisterBankInfo::PartialMapping * BreakDown)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
checkValueMappings()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
ARMRegisterBankInfo(const TargetRegisterInfo & TRI)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 &
getRegBankFromRegClass(const TargetRegisterClass & RC,LLT) const174480093f4SDimitry 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 &
getInstrMapping(const MachineInstr & MI) const2120b57cec5SDimitry 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