1*0b57cec5SDimitry Andric //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// \file 9*0b57cec5SDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for ARM. 10*0b57cec5SDimitry Andric /// \todo This should be generated by TableGen. 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "ARMRegisterBankInfo.h" 14*0b57cec5SDimitry Andric #include "ARMInstrInfo.h" // For the register classes 15*0b57cec5SDimitry Andric #include "ARMSubtarget.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBank.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric #define GET_TARGET_REGBANK_IMPL 22*0b57cec5SDimitry Andric #include "ARMGenRegisterBank.inc" 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric using namespace llvm; 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric // FIXME: TableGen this. 27*0b57cec5SDimitry Andric // If it grows too much and TableGen still isn't ready to do the job, extract it 28*0b57cec5SDimitry Andric // into an ARMGenRegisterBankInfo.def (similar to AArch64). 29*0b57cec5SDimitry Andric namespace llvm { 30*0b57cec5SDimitry Andric namespace ARM { 31*0b57cec5SDimitry Andric enum PartialMappingIdx { 32*0b57cec5SDimitry Andric PMI_GPR, 33*0b57cec5SDimitry Andric PMI_SPR, 34*0b57cec5SDimitry Andric PMI_DPR, 35*0b57cec5SDimitry Andric PMI_Min = PMI_GPR, 36*0b57cec5SDimitry Andric }; 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{ 39*0b57cec5SDimitry Andric // GPR Partial Mapping 40*0b57cec5SDimitry Andric {0, 32, GPRRegBank}, 41*0b57cec5SDimitry Andric // SPR Partial Mapping 42*0b57cec5SDimitry Andric {0, 32, FPRRegBank}, 43*0b57cec5SDimitry Andric // DPR Partial Mapping 44*0b57cec5SDimitry Andric {0, 64, FPRRegBank}, 45*0b57cec5SDimitry Andric }; 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric #ifndef NDEBUG 48*0b57cec5SDimitry Andric static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM, 49*0b57cec5SDimitry Andric unsigned Start, unsigned Length, 50*0b57cec5SDimitry Andric unsigned RegBankID) { 51*0b57cec5SDimitry Andric return PM.StartIdx == Start && PM.Length == Length && 52*0b57cec5SDimitry Andric PM.RegBank->getID() == RegBankID; 53*0b57cec5SDimitry Andric } 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric static void checkPartialMappings() { 56*0b57cec5SDimitry Andric assert( 57*0b57cec5SDimitry Andric checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) && 58*0b57cec5SDimitry Andric "Wrong mapping for GPR"); 59*0b57cec5SDimitry Andric assert( 60*0b57cec5SDimitry Andric checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) && 61*0b57cec5SDimitry Andric "Wrong mapping for SPR"); 62*0b57cec5SDimitry Andric assert( 63*0b57cec5SDimitry Andric checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) && 64*0b57cec5SDimitry Andric "Wrong mapping for DPR"); 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric #endif 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric enum ValueMappingIdx { 69*0b57cec5SDimitry Andric InvalidIdx = 0, 70*0b57cec5SDimitry Andric GPR3OpsIdx = 1, 71*0b57cec5SDimitry Andric SPR3OpsIdx = 4, 72*0b57cec5SDimitry Andric DPR3OpsIdx = 7, 73*0b57cec5SDimitry Andric }; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = { 76*0b57cec5SDimitry Andric // invalid 77*0b57cec5SDimitry Andric {nullptr, 0}, 78*0b57cec5SDimitry Andric // 3 ops in GPRs 79*0b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 80*0b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 81*0b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 82*0b57cec5SDimitry Andric // 3 ops in SPRs 83*0b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 84*0b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 85*0b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 86*0b57cec5SDimitry Andric // 3 ops in DPRs 87*0b57cec5SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}, 88*0b57cec5SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}, 89*0b57cec5SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}}; 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric #ifndef NDEBUG 92*0b57cec5SDimitry Andric static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM, 93*0b57cec5SDimitry Andric RegisterBankInfo::PartialMapping *BreakDown) { 94*0b57cec5SDimitry Andric return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown; 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric static void checkValueMappings() { 98*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx], 99*0b57cec5SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 100*0b57cec5SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 101*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1], 102*0b57cec5SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 103*0b57cec5SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 104*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2], 105*0b57cec5SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 106*0b57cec5SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx], 109*0b57cec5SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 110*0b57cec5SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 111*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1], 112*0b57cec5SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 113*0b57cec5SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 114*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2], 115*0b57cec5SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 116*0b57cec5SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx], 119*0b57cec5SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 120*0b57cec5SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 121*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1], 122*0b57cec5SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 123*0b57cec5SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 124*0b57cec5SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2], 125*0b57cec5SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 126*0b57cec5SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric #endif 129*0b57cec5SDimitry Andric } // end namespace arm 130*0b57cec5SDimitry Andric } // end namespace llvm 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 133*0b57cec5SDimitry Andric : ARMGenRegisterBankInfo() { 134*0b57cec5SDimitry Andric static bool AlreadyInit = false; 135*0b57cec5SDimitry Andric // We have only one set of register banks, whatever the subtarget 136*0b57cec5SDimitry Andric // is. Therefore, the initialization of the RegBanks table should be 137*0b57cec5SDimitry Andric // done only once. Indeed the table of all register banks 138*0b57cec5SDimitry Andric // (ARM::RegBanks) is unique in the compiler. At some point, it 139*0b57cec5SDimitry Andric // will get tablegen'ed and the whole constructor becomes empty. 140*0b57cec5SDimitry Andric if (AlreadyInit) 141*0b57cec5SDimitry Andric return; 142*0b57cec5SDimitry Andric AlreadyInit = true; 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 145*0b57cec5SDimitry Andric (void)RBGPR; 146*0b57cec5SDimitry Andric assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric // Initialize the GPR bank. 149*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 150*0b57cec5SDimitry Andric "Subclass not added?"); 151*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 152*0b57cec5SDimitry Andric "Subclass not added?"); 153*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 154*0b57cec5SDimitry Andric "Subclass not added?"); 155*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 156*0b57cec5SDimitry Andric "Subclass not added?"); 157*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 158*0b57cec5SDimitry Andric "Subclass not added?"); 159*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 160*0b57cec5SDimitry Andric "Subclass not added?"); 161*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 162*0b57cec5SDimitry Andric "Subclass not added?"); 163*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPREven_and_tGPR_and_tcGPRRegClassID)) && 164*0b57cec5SDimitry Andric "Subclass not added?"); 165*0b57cec5SDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) && 166*0b57cec5SDimitry Andric "Subclass not added?"); 167*0b57cec5SDimitry Andric assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric #ifndef NDEBUG 170*0b57cec5SDimitry Andric ARM::checkPartialMappings(); 171*0b57cec5SDimitry Andric ARM::checkValueMappings(); 172*0b57cec5SDimitry Andric #endif 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 176*0b57cec5SDimitry Andric const TargetRegisterClass &RC) const { 177*0b57cec5SDimitry Andric using namespace ARM; 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric switch (RC.getID()) { 180*0b57cec5SDimitry Andric case GPRRegClassID: 181*0b57cec5SDimitry Andric case GPRwithAPSRRegClassID: 182*0b57cec5SDimitry Andric case GPRnopcRegClassID: 183*0b57cec5SDimitry Andric case rGPRRegClassID: 184*0b57cec5SDimitry Andric case GPRspRegClassID: 185*0b57cec5SDimitry Andric case tGPR_and_tcGPRRegClassID: 186*0b57cec5SDimitry Andric case tcGPRRegClassID: 187*0b57cec5SDimitry Andric case tGPRRegClassID: 188*0b57cec5SDimitry Andric case tGPREvenRegClassID: 189*0b57cec5SDimitry Andric case tGPROddRegClassID: 190*0b57cec5SDimitry Andric case tGPR_and_tGPREvenRegClassID: 191*0b57cec5SDimitry Andric case tGPR_and_tGPROddRegClassID: 192*0b57cec5SDimitry Andric case tGPREven_and_tcGPRRegClassID: 193*0b57cec5SDimitry Andric case tGPREven_and_tGPR_and_tcGPRRegClassID: 194*0b57cec5SDimitry Andric case tGPROdd_and_tcGPRRegClassID: 195*0b57cec5SDimitry Andric return getRegBank(ARM::GPRRegBankID); 196*0b57cec5SDimitry Andric case HPRRegClassID: 197*0b57cec5SDimitry Andric case SPR_8RegClassID: 198*0b57cec5SDimitry Andric case SPRRegClassID: 199*0b57cec5SDimitry Andric case DPR_8RegClassID: 200*0b57cec5SDimitry Andric case DPRRegClassID: 201*0b57cec5SDimitry Andric case QPRRegClassID: 202*0b57cec5SDimitry Andric return getRegBank(ARM::FPRRegBankID); 203*0b57cec5SDimitry Andric default: 204*0b57cec5SDimitry Andric llvm_unreachable("Unsupported register kind"); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric llvm_unreachable("Switch should handle all register classes"); 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping & 211*0b57cec5SDimitry Andric ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 212*0b57cec5SDimitry Andric auto Opc = MI.getOpcode(); 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric // Try the default logic for non-generic instructions that are either copies 215*0b57cec5SDimitry Andric // or already have some operands assigned to banks. 216*0b57cec5SDimitry Andric if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 217*0b57cec5SDimitry Andric const InstructionMapping &Mapping = getInstrMappingImpl(MI); 218*0b57cec5SDimitry Andric if (Mapping.isValid()) 219*0b57cec5SDimitry Andric return Mapping; 220*0b57cec5SDimitry Andric } 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric using namespace TargetOpcode; 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 225*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 226*0b57cec5SDimitry Andric unsigned NumOperands = MI.getNumOperands(); 227*0b57cec5SDimitry Andric const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric switch (Opc) { 230*0b57cec5SDimitry Andric case G_ADD: 231*0b57cec5SDimitry Andric case G_SUB: { 232*0b57cec5SDimitry Andric // Integer operations where the source and destination are in the 233*0b57cec5SDimitry Andric // same register class. 234*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 235*0b57cec5SDimitry Andric OperandsMapping = Ty.getSizeInBits() == 64 236*0b57cec5SDimitry Andric ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 237*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 238*0b57cec5SDimitry Andric break; 239*0b57cec5SDimitry Andric } 240*0b57cec5SDimitry Andric case G_MUL: 241*0b57cec5SDimitry Andric case G_AND: 242*0b57cec5SDimitry Andric case G_OR: 243*0b57cec5SDimitry Andric case G_XOR: 244*0b57cec5SDimitry Andric case G_LSHR: 245*0b57cec5SDimitry Andric case G_ASHR: 246*0b57cec5SDimitry Andric case G_SHL: 247*0b57cec5SDimitry Andric case G_SDIV: 248*0b57cec5SDimitry Andric case G_UDIV: 249*0b57cec5SDimitry Andric case G_SEXT: 250*0b57cec5SDimitry Andric case G_ZEXT: 251*0b57cec5SDimitry Andric case G_ANYEXT: 252*0b57cec5SDimitry Andric case G_GEP: 253*0b57cec5SDimitry Andric case G_INTTOPTR: 254*0b57cec5SDimitry Andric case G_PTRTOINT: 255*0b57cec5SDimitry Andric case G_CTLZ: 256*0b57cec5SDimitry Andric // FIXME: We're abusing the fact that everything lives in a GPR for now; in 257*0b57cec5SDimitry Andric // the real world we would use different mappings. 258*0b57cec5SDimitry Andric OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 259*0b57cec5SDimitry Andric break; 260*0b57cec5SDimitry Andric case G_TRUNC: { 261*0b57cec5SDimitry Andric // In some cases we may end up with a G_TRUNC from a 64-bit value to a 262*0b57cec5SDimitry Andric // 32-bit value. This isn't a real floating point trunc (that would be a 263*0b57cec5SDimitry Andric // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear 264*0b57cec5SDimitry Andric // because the legalizer doesn't distinguish between integer and floating 265*0b57cec5SDimitry Andric // point values so it may leave some 64-bit integers un-narrowed. Until we 266*0b57cec5SDimitry Andric // have a more principled solution that doesn't let such things sneak all 267*0b57cec5SDimitry Andric // the way to this point, just map the source to a DPR and the destination 268*0b57cec5SDimitry Andric // to a GPR. 269*0b57cec5SDimitry Andric LLT LargeTy = MRI.getType(MI.getOperand(1).getReg()); 270*0b57cec5SDimitry Andric OperandsMapping = 271*0b57cec5SDimitry Andric LargeTy.getSizeInBits() <= 32 272*0b57cec5SDimitry Andric ? &ARM::ValueMappings[ARM::GPR3OpsIdx] 273*0b57cec5SDimitry Andric : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 274*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 275*0b57cec5SDimitry Andric break; 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric case G_LOAD: 278*0b57cec5SDimitry Andric case G_STORE: { 279*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 280*0b57cec5SDimitry Andric OperandsMapping = 281*0b57cec5SDimitry Andric Ty.getSizeInBits() == 64 282*0b57cec5SDimitry Andric ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 283*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 284*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 285*0b57cec5SDimitry Andric break; 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric case G_FADD: 288*0b57cec5SDimitry Andric case G_FSUB: 289*0b57cec5SDimitry Andric case G_FMUL: 290*0b57cec5SDimitry Andric case G_FDIV: 291*0b57cec5SDimitry Andric case G_FNEG: { 292*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 293*0b57cec5SDimitry Andric OperandsMapping =Ty.getSizeInBits() == 64 294*0b57cec5SDimitry Andric ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 295*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 296*0b57cec5SDimitry Andric break; 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric case G_FMA: { 299*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 300*0b57cec5SDimitry Andric OperandsMapping = 301*0b57cec5SDimitry Andric Ty.getSizeInBits() == 64 302*0b57cec5SDimitry Andric ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 303*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx], 304*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx], 305*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 306*0b57cec5SDimitry Andric : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 307*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::SPR3OpsIdx], 308*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::SPR3OpsIdx], 309*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 310*0b57cec5SDimitry Andric break; 311*0b57cec5SDimitry Andric } 312*0b57cec5SDimitry Andric case G_FPEXT: { 313*0b57cec5SDimitry Andric LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 314*0b57cec5SDimitry Andric LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 315*0b57cec5SDimitry Andric if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32) 316*0b57cec5SDimitry Andric OperandsMapping = 317*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 318*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 319*0b57cec5SDimitry Andric break; 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric case G_FPTRUNC: { 322*0b57cec5SDimitry Andric LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 323*0b57cec5SDimitry Andric LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 324*0b57cec5SDimitry Andric if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64) 325*0b57cec5SDimitry Andric OperandsMapping = 326*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 327*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 328*0b57cec5SDimitry Andric break; 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric case G_FPTOSI: 331*0b57cec5SDimitry Andric case G_FPTOUI: { 332*0b57cec5SDimitry Andric LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 333*0b57cec5SDimitry Andric LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 334*0b57cec5SDimitry Andric if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) && 335*0b57cec5SDimitry Andric ToTy.getSizeInBits() == 32) 336*0b57cec5SDimitry Andric OperandsMapping = 337*0b57cec5SDimitry Andric FromTy.getSizeInBits() == 64 338*0b57cec5SDimitry Andric ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 339*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 340*0b57cec5SDimitry Andric : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 341*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 342*0b57cec5SDimitry Andric break; 343*0b57cec5SDimitry Andric } 344*0b57cec5SDimitry Andric case G_SITOFP: 345*0b57cec5SDimitry Andric case G_UITOFP: { 346*0b57cec5SDimitry Andric LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 347*0b57cec5SDimitry Andric LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 348*0b57cec5SDimitry Andric if (FromTy.getSizeInBits() == 32 && 349*0b57cec5SDimitry Andric (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64)) 350*0b57cec5SDimitry Andric OperandsMapping = 351*0b57cec5SDimitry Andric ToTy.getSizeInBits() == 64 352*0b57cec5SDimitry Andric ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 353*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 354*0b57cec5SDimitry Andric : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 355*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 356*0b57cec5SDimitry Andric break; 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric case G_FCONSTANT: { 359*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 360*0b57cec5SDimitry Andric OperandsMapping = getOperandsMapping( 361*0b57cec5SDimitry Andric {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 362*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::SPR3OpsIdx], 363*0b57cec5SDimitry Andric nullptr}); 364*0b57cec5SDimitry Andric break; 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric case G_CONSTANT: 367*0b57cec5SDimitry Andric case G_FRAME_INDEX: 368*0b57cec5SDimitry Andric case G_GLOBAL_VALUE: 369*0b57cec5SDimitry Andric OperandsMapping = 370*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 371*0b57cec5SDimitry Andric break; 372*0b57cec5SDimitry Andric case G_SELECT: { 373*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 374*0b57cec5SDimitry Andric (void)Ty; 375*0b57cec5SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(1).getReg()); 376*0b57cec5SDimitry Andric (void)Ty2; 377*0b57cec5SDimitry Andric assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT"); 378*0b57cec5SDimitry Andric assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT"); 379*0b57cec5SDimitry Andric OperandsMapping = 380*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 381*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 382*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 383*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 384*0b57cec5SDimitry Andric break; 385*0b57cec5SDimitry Andric } 386*0b57cec5SDimitry Andric case G_ICMP: { 387*0b57cec5SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 388*0b57cec5SDimitry Andric (void)Ty2; 389*0b57cec5SDimitry Andric assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP"); 390*0b57cec5SDimitry Andric OperandsMapping = 391*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 392*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 393*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 394*0b57cec5SDimitry Andric break; 395*0b57cec5SDimitry Andric } 396*0b57cec5SDimitry Andric case G_FCMP: { 397*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 398*0b57cec5SDimitry Andric (void)Ty; 399*0b57cec5SDimitry Andric LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 400*0b57cec5SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 401*0b57cec5SDimitry Andric (void)Ty2; 402*0b57cec5SDimitry Andric assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP"); 403*0b57cec5SDimitry Andric assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 404*0b57cec5SDimitry Andric "Mismatched operand sizes for G_FCMP"); 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric unsigned Size = Ty1.getSizeInBits(); 407*0b57cec5SDimitry Andric assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx] 410*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::DPR3OpsIdx]; 411*0b57cec5SDimitry Andric OperandsMapping = 412*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 413*0b57cec5SDimitry Andric FPRValueMapping, FPRValueMapping}); 414*0b57cec5SDimitry Andric break; 415*0b57cec5SDimitry Andric } 416*0b57cec5SDimitry Andric case G_MERGE_VALUES: { 417*0b57cec5SDimitry Andric // We only support G_MERGE_VALUES for creating a double precision floating 418*0b57cec5SDimitry Andric // point value out of two GPRs. 419*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 420*0b57cec5SDimitry Andric LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 421*0b57cec5SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 422*0b57cec5SDimitry Andric if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 423*0b57cec5SDimitry Andric Ty2.getSizeInBits() != 32) 424*0b57cec5SDimitry Andric return getInvalidInstructionMapping(); 425*0b57cec5SDimitry Andric OperandsMapping = 426*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 427*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 428*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 429*0b57cec5SDimitry Andric break; 430*0b57cec5SDimitry Andric } 431*0b57cec5SDimitry Andric case G_UNMERGE_VALUES: { 432*0b57cec5SDimitry Andric // We only support G_UNMERGE_VALUES for splitting a double precision 433*0b57cec5SDimitry Andric // floating point value into two GPRs. 434*0b57cec5SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 435*0b57cec5SDimitry Andric LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 436*0b57cec5SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 437*0b57cec5SDimitry Andric if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 438*0b57cec5SDimitry Andric Ty2.getSizeInBits() != 64) 439*0b57cec5SDimitry Andric return getInvalidInstructionMapping(); 440*0b57cec5SDimitry Andric OperandsMapping = 441*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 442*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 443*0b57cec5SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 444*0b57cec5SDimitry Andric break; 445*0b57cec5SDimitry Andric } 446*0b57cec5SDimitry Andric case G_BR: 447*0b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({nullptr}); 448*0b57cec5SDimitry Andric break; 449*0b57cec5SDimitry Andric case G_BRCOND: 450*0b57cec5SDimitry Andric OperandsMapping = 451*0b57cec5SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 452*0b57cec5SDimitry Andric break; 453*0b57cec5SDimitry Andric case DBG_VALUE: { 454*0b57cec5SDimitry Andric SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands); 455*0b57cec5SDimitry Andric const MachineOperand &MaybeReg = MI.getOperand(0); 456*0b57cec5SDimitry Andric if (MaybeReg.isReg() && MaybeReg.getReg()) { 457*0b57cec5SDimitry Andric unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits(); 458*0b57cec5SDimitry Andric if (Size > 32 && Size != 64) 459*0b57cec5SDimitry Andric return getInvalidInstructionMapping(); 460*0b57cec5SDimitry Andric OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 461*0b57cec5SDimitry Andric : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 462*0b57cec5SDimitry Andric } 463*0b57cec5SDimitry Andric OperandsMapping = getOperandsMapping(OperandBanks); 464*0b57cec5SDimitry Andric break; 465*0b57cec5SDimitry Andric } 466*0b57cec5SDimitry Andric default: 467*0b57cec5SDimitry Andric return getInvalidInstructionMapping(); 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric #ifndef NDEBUG 471*0b57cec5SDimitry Andric for (unsigned i = 0; i < NumOperands; i++) { 472*0b57cec5SDimitry Andric for (const auto &Mapping : OperandsMapping[i]) { 473*0b57cec5SDimitry Andric assert( 474*0b57cec5SDimitry Andric (Mapping.RegBank->getID() != ARM::FPRRegBankID || 475*0b57cec5SDimitry Andric MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) && 476*0b57cec5SDimitry Andric "Trying to use floating point register bank on target without vfp"); 477*0b57cec5SDimitry Andric } 478*0b57cec5SDimitry Andric } 479*0b57cec5SDimitry Andric #endif 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 482*0b57cec5SDimitry Andric NumOperands); 483*0b57cec5SDimitry Andric } 484