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