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