1bdd1243dSDimitry Andric //===-- RISCVRegisterBankInfo.cpp -------------------------------*- C++ -*-===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric /// \file 906c3fb27SDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for RISC-V. 10bdd1243dSDimitry Andric /// \todo This should be generated by TableGen. 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include "RISCVRegisterBankInfo.h" 14bdd1243dSDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h" 15*5f757f3fSDimitry Andric #include "RISCVSubtarget.h" 16bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 17bdd1243dSDimitry Andric #include "llvm/CodeGen/RegisterBank.h" 18bdd1243dSDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 19bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 20bdd1243dSDimitry Andric 21bdd1243dSDimitry Andric #define GET_TARGET_REGBANK_IMPL 22bdd1243dSDimitry Andric #include "RISCVGenRegisterBank.inc" 23bdd1243dSDimitry Andric 24*5f757f3fSDimitry Andric namespace llvm { 25*5f757f3fSDimitry Andric namespace RISCV { 26*5f757f3fSDimitry Andric 27*5f757f3fSDimitry Andric const RegisterBankInfo::PartialMapping PartMappings[] = { 28*5f757f3fSDimitry Andric {0, 32, GPRBRegBank}, 29*5f757f3fSDimitry Andric {0, 64, GPRBRegBank}, 30*5f757f3fSDimitry Andric {0, 32, FPRBRegBank}, 31*5f757f3fSDimitry Andric {0, 64, FPRBRegBank}, 32*5f757f3fSDimitry Andric }; 33*5f757f3fSDimitry Andric 34*5f757f3fSDimitry Andric enum PartialMappingIdx { 35*5f757f3fSDimitry Andric PMI_GPRB32 = 0, 36*5f757f3fSDimitry Andric PMI_GPRB64 = 1, 37*5f757f3fSDimitry Andric PMI_FPRB32 = 2, 38*5f757f3fSDimitry Andric PMI_FPRB64 = 3, 39*5f757f3fSDimitry Andric }; 40*5f757f3fSDimitry Andric 41*5f757f3fSDimitry Andric const RegisterBankInfo::ValueMapping ValueMappings[] = { 42*5f757f3fSDimitry Andric // Invalid value mapping. 43*5f757f3fSDimitry Andric {nullptr, 0}, 44*5f757f3fSDimitry Andric // Maximum 3 GPR operands; 32 bit. 45*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 46*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 47*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 48*5f757f3fSDimitry Andric // Maximum 3 GPR operands; 64 bit. 49*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 50*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 51*5f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 52*5f757f3fSDimitry Andric // Maximum 3 FPR operands; 32 bit. 53*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 54*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 55*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 56*5f757f3fSDimitry Andric // Maximum 3 FPR operands; 64 bit. 57*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 58*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 59*5f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 60*5f757f3fSDimitry Andric }; 61*5f757f3fSDimitry Andric 62*5f757f3fSDimitry Andric enum ValueMappingIdx { 63*5f757f3fSDimitry Andric InvalidIdx = 0, 64*5f757f3fSDimitry Andric GPRB32Idx = 1, 65*5f757f3fSDimitry Andric GPRB64Idx = 4, 66*5f757f3fSDimitry Andric FPRB32Idx = 7, 67*5f757f3fSDimitry Andric FPRB64Idx = 10, 68*5f757f3fSDimitry Andric }; 69*5f757f3fSDimitry Andric } // namespace RISCV 70*5f757f3fSDimitry Andric } // namespace llvm 71*5f757f3fSDimitry Andric 72bdd1243dSDimitry Andric using namespace llvm; 73bdd1243dSDimitry Andric 7406c3fb27SDimitry Andric RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode) 7506c3fb27SDimitry Andric : RISCVGenRegisterBankInfo(HwMode) {} 76*5f757f3fSDimitry Andric 77*5f757f3fSDimitry Andric const RegisterBank & 78*5f757f3fSDimitry Andric RISCVRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 79*5f757f3fSDimitry Andric LLT Ty) const { 80*5f757f3fSDimitry Andric switch (RC.getID()) { 81*5f757f3fSDimitry Andric default: 82*5f757f3fSDimitry Andric llvm_unreachable("Register class not supported"); 83*5f757f3fSDimitry Andric case RISCV::GPRRegClassID: 84*5f757f3fSDimitry Andric case RISCV::GPRF16RegClassID: 85*5f757f3fSDimitry Andric case RISCV::GPRF32RegClassID: 86*5f757f3fSDimitry Andric case RISCV::GPRNoX0RegClassID: 87*5f757f3fSDimitry Andric case RISCV::GPRNoX0X2RegClassID: 88*5f757f3fSDimitry Andric case RISCV::GPRJALRRegClassID: 89*5f757f3fSDimitry Andric case RISCV::GPRTCRegClassID: 90*5f757f3fSDimitry Andric case RISCV::GPRC_and_GPRTCRegClassID: 91*5f757f3fSDimitry Andric case RISCV::GPRCRegClassID: 92*5f757f3fSDimitry Andric case RISCV::GPRC_and_SR07RegClassID: 93*5f757f3fSDimitry Andric case RISCV::SR07RegClassID: 94*5f757f3fSDimitry Andric case RISCV::SPRegClassID: 95*5f757f3fSDimitry Andric case RISCV::GPRX0RegClassID: 96*5f757f3fSDimitry Andric return getRegBank(RISCV::GPRBRegBankID); 97*5f757f3fSDimitry Andric case RISCV::FPR64RegClassID: 98*5f757f3fSDimitry Andric case RISCV::FPR16RegClassID: 99*5f757f3fSDimitry Andric case RISCV::FPR32RegClassID: 100*5f757f3fSDimitry Andric case RISCV::FPR64CRegClassID: 101*5f757f3fSDimitry Andric case RISCV::FPR32CRegClassID: 102*5f757f3fSDimitry Andric return getRegBank(RISCV::FPRBRegBankID); 103*5f757f3fSDimitry Andric case RISCV::VMRegClassID: 104*5f757f3fSDimitry Andric case RISCV::VRRegClassID: 105*5f757f3fSDimitry Andric case RISCV::VRNoV0RegClassID: 106*5f757f3fSDimitry Andric case RISCV::VRM2RegClassID: 107*5f757f3fSDimitry Andric case RISCV::VRM2NoV0RegClassID: 108*5f757f3fSDimitry Andric case RISCV::VRM4RegClassID: 109*5f757f3fSDimitry Andric case RISCV::VRM4NoV0RegClassID: 110*5f757f3fSDimitry Andric case RISCV::VMV0RegClassID: 111*5f757f3fSDimitry Andric case RISCV::VRM2_with_sub_vrm1_0_in_VMV0RegClassID: 112*5f757f3fSDimitry Andric case RISCV::VRM4_with_sub_vrm1_0_in_VMV0RegClassID: 113*5f757f3fSDimitry Andric case RISCV::VRM8RegClassID: 114*5f757f3fSDimitry Andric case RISCV::VRM8NoV0RegClassID: 115*5f757f3fSDimitry Andric case RISCV::VRM8_with_sub_vrm1_0_in_VMV0RegClassID: 116*5f757f3fSDimitry Andric return getRegBank(RISCV::VRBRegBankID); 117*5f757f3fSDimitry Andric } 118*5f757f3fSDimitry Andric } 119*5f757f3fSDimitry Andric 120*5f757f3fSDimitry Andric static const RegisterBankInfo::ValueMapping *getFPValueMapping(unsigned Size) { 121*5f757f3fSDimitry Andric assert(Size == 32 || Size == 64); 122*5f757f3fSDimitry Andric unsigned Idx = Size == 64 ? RISCV::FPRB64Idx : RISCV::FPRB32Idx; 123*5f757f3fSDimitry Andric return &RISCV::ValueMappings[Idx]; 124*5f757f3fSDimitry Andric } 125*5f757f3fSDimitry Andric 126*5f757f3fSDimitry Andric /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode, 127*5f757f3fSDimitry Andric /// having only floating-point operands. 128*5f757f3fSDimitry Andric /// FIXME: this is copied from target AArch64. Needs some code refactor here to 129*5f757f3fSDimitry Andric /// put this function in GlobalISel/Utils.cpp. 130*5f757f3fSDimitry Andric static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) { 131*5f757f3fSDimitry Andric switch (Opc) { 132*5f757f3fSDimitry Andric case TargetOpcode::G_FADD: 133*5f757f3fSDimitry Andric case TargetOpcode::G_FSUB: 134*5f757f3fSDimitry Andric case TargetOpcode::G_FMUL: 135*5f757f3fSDimitry Andric case TargetOpcode::G_FMA: 136*5f757f3fSDimitry Andric case TargetOpcode::G_FDIV: 137*5f757f3fSDimitry Andric case TargetOpcode::G_FCONSTANT: 138*5f757f3fSDimitry Andric case TargetOpcode::G_FPEXT: 139*5f757f3fSDimitry Andric case TargetOpcode::G_FPTRUNC: 140*5f757f3fSDimitry Andric case TargetOpcode::G_FCEIL: 141*5f757f3fSDimitry Andric case TargetOpcode::G_FFLOOR: 142*5f757f3fSDimitry Andric case TargetOpcode::G_FNEARBYINT: 143*5f757f3fSDimitry Andric case TargetOpcode::G_FNEG: 144*5f757f3fSDimitry Andric case TargetOpcode::G_FCOPYSIGN: 145*5f757f3fSDimitry Andric case TargetOpcode::G_FCOS: 146*5f757f3fSDimitry Andric case TargetOpcode::G_FSIN: 147*5f757f3fSDimitry Andric case TargetOpcode::G_FLOG10: 148*5f757f3fSDimitry Andric case TargetOpcode::G_FLOG: 149*5f757f3fSDimitry Andric case TargetOpcode::G_FLOG2: 150*5f757f3fSDimitry Andric case TargetOpcode::G_FSQRT: 151*5f757f3fSDimitry Andric case TargetOpcode::G_FABS: 152*5f757f3fSDimitry Andric case TargetOpcode::G_FEXP: 153*5f757f3fSDimitry Andric case TargetOpcode::G_FRINT: 154*5f757f3fSDimitry Andric case TargetOpcode::G_INTRINSIC_TRUNC: 155*5f757f3fSDimitry Andric case TargetOpcode::G_INTRINSIC_ROUND: 156*5f757f3fSDimitry Andric case TargetOpcode::G_INTRINSIC_ROUNDEVEN: 157*5f757f3fSDimitry Andric case TargetOpcode::G_FMAXNUM: 158*5f757f3fSDimitry Andric case TargetOpcode::G_FMINNUM: 159*5f757f3fSDimitry Andric case TargetOpcode::G_FMAXIMUM: 160*5f757f3fSDimitry Andric case TargetOpcode::G_FMINIMUM: 161*5f757f3fSDimitry Andric return true; 162*5f757f3fSDimitry Andric } 163*5f757f3fSDimitry Andric return false; 164*5f757f3fSDimitry Andric } 165*5f757f3fSDimitry Andric 166*5f757f3fSDimitry Andric // TODO: Make this more like AArch64? 167*5f757f3fSDimitry Andric bool RISCVRegisterBankInfo::hasFPConstraints( 168*5f757f3fSDimitry Andric const MachineInstr &MI, const MachineRegisterInfo &MRI, 169*5f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 170*5f757f3fSDimitry Andric if (isPreISelGenericFloatingPointOpcode(MI.getOpcode())) 171*5f757f3fSDimitry Andric return true; 172*5f757f3fSDimitry Andric 173*5f757f3fSDimitry Andric // If we have a copy instruction, we could be feeding floating point 174*5f757f3fSDimitry Andric // instructions. 175*5f757f3fSDimitry Andric if (MI.getOpcode() != TargetOpcode::COPY) 176*5f757f3fSDimitry Andric return false; 177*5f757f3fSDimitry Andric 178*5f757f3fSDimitry Andric return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) == &RISCV::FPRBRegBank; 179*5f757f3fSDimitry Andric } 180*5f757f3fSDimitry Andric 181*5f757f3fSDimitry Andric bool RISCVRegisterBankInfo::onlyUsesFP(const MachineInstr &MI, 182*5f757f3fSDimitry Andric const MachineRegisterInfo &MRI, 183*5f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 184*5f757f3fSDimitry Andric switch (MI.getOpcode()) { 185*5f757f3fSDimitry Andric case TargetOpcode::G_FPTOSI: 186*5f757f3fSDimitry Andric case TargetOpcode::G_FPTOUI: 187*5f757f3fSDimitry Andric case TargetOpcode::G_FCMP: 188*5f757f3fSDimitry Andric return true; 189*5f757f3fSDimitry Andric default: 190*5f757f3fSDimitry Andric break; 191*5f757f3fSDimitry Andric } 192*5f757f3fSDimitry Andric 193*5f757f3fSDimitry Andric return hasFPConstraints(MI, MRI, TRI); 194*5f757f3fSDimitry Andric } 195*5f757f3fSDimitry Andric 196*5f757f3fSDimitry Andric bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, 197*5f757f3fSDimitry Andric const MachineRegisterInfo &MRI, 198*5f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 199*5f757f3fSDimitry Andric switch (MI.getOpcode()) { 200*5f757f3fSDimitry Andric case TargetOpcode::G_SITOFP: 201*5f757f3fSDimitry Andric case TargetOpcode::G_UITOFP: 202*5f757f3fSDimitry Andric return true; 203*5f757f3fSDimitry Andric default: 204*5f757f3fSDimitry Andric break; 205*5f757f3fSDimitry Andric } 206*5f757f3fSDimitry Andric 207*5f757f3fSDimitry Andric return hasFPConstraints(MI, MRI, TRI); 208*5f757f3fSDimitry Andric } 209*5f757f3fSDimitry Andric 210*5f757f3fSDimitry Andric bool RISCVRegisterBankInfo::anyUseOnlyUseFP( 211*5f757f3fSDimitry Andric Register Def, const MachineRegisterInfo &MRI, 212*5f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 213*5f757f3fSDimitry Andric return any_of( 214*5f757f3fSDimitry Andric MRI.use_nodbg_instructions(Def), 215*5f757f3fSDimitry Andric [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); }); 216*5f757f3fSDimitry Andric } 217*5f757f3fSDimitry Andric 218*5f757f3fSDimitry Andric const RegisterBankInfo::InstructionMapping & 219*5f757f3fSDimitry Andric RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 220*5f757f3fSDimitry Andric const unsigned Opc = MI.getOpcode(); 221*5f757f3fSDimitry Andric 222*5f757f3fSDimitry Andric // Try the default logic for non-generic instructions that are either copies 223*5f757f3fSDimitry Andric // or already have some operands assigned to banks. 224*5f757f3fSDimitry Andric if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 225*5f757f3fSDimitry Andric const InstructionMapping &Mapping = getInstrMappingImpl(MI); 226*5f757f3fSDimitry Andric if (Mapping.isValid()) 227*5f757f3fSDimitry Andric return Mapping; 228*5f757f3fSDimitry Andric } 229*5f757f3fSDimitry Andric 230*5f757f3fSDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 231*5f757f3fSDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 232*5f757f3fSDimitry Andric const TargetSubtargetInfo &STI = MF.getSubtarget(); 233*5f757f3fSDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 234*5f757f3fSDimitry Andric 235*5f757f3fSDimitry Andric unsigned GPRSize = getMaximumSize(RISCV::GPRBRegBankID); 236*5f757f3fSDimitry Andric assert((GPRSize == 32 || GPRSize == 64) && "Unexpected GPR size"); 237*5f757f3fSDimitry Andric 238*5f757f3fSDimitry Andric unsigned NumOperands = MI.getNumOperands(); 239*5f757f3fSDimitry Andric const ValueMapping *GPRValueMapping = 240*5f757f3fSDimitry Andric &RISCV::ValueMappings[GPRSize == 64 ? RISCV::GPRB64Idx 241*5f757f3fSDimitry Andric : RISCV::GPRB32Idx]; 242*5f757f3fSDimitry Andric 243*5f757f3fSDimitry Andric switch (Opc) { 244*5f757f3fSDimitry Andric case TargetOpcode::G_ADD: 245*5f757f3fSDimitry Andric case TargetOpcode::G_SUB: 246*5f757f3fSDimitry Andric case TargetOpcode::G_SHL: 247*5f757f3fSDimitry Andric case TargetOpcode::G_ASHR: 248*5f757f3fSDimitry Andric case TargetOpcode::G_LSHR: 249*5f757f3fSDimitry Andric case TargetOpcode::G_AND: 250*5f757f3fSDimitry Andric case TargetOpcode::G_OR: 251*5f757f3fSDimitry Andric case TargetOpcode::G_XOR: 252*5f757f3fSDimitry Andric case TargetOpcode::G_MUL: 253*5f757f3fSDimitry Andric case TargetOpcode::G_SDIV: 254*5f757f3fSDimitry Andric case TargetOpcode::G_SREM: 255*5f757f3fSDimitry Andric case TargetOpcode::G_SMULH: 256*5f757f3fSDimitry Andric case TargetOpcode::G_SMAX: 257*5f757f3fSDimitry Andric case TargetOpcode::G_SMIN: 258*5f757f3fSDimitry Andric case TargetOpcode::G_UDIV: 259*5f757f3fSDimitry Andric case TargetOpcode::G_UREM: 260*5f757f3fSDimitry Andric case TargetOpcode::G_UMULH: 261*5f757f3fSDimitry Andric case TargetOpcode::G_UMAX: 262*5f757f3fSDimitry Andric case TargetOpcode::G_UMIN: 263*5f757f3fSDimitry Andric case TargetOpcode::G_PTR_ADD: 264*5f757f3fSDimitry Andric case TargetOpcode::G_PTRTOINT: 265*5f757f3fSDimitry Andric case TargetOpcode::G_INTTOPTR: 266*5f757f3fSDimitry Andric case TargetOpcode::G_TRUNC: 267*5f757f3fSDimitry Andric case TargetOpcode::G_ANYEXT: 268*5f757f3fSDimitry Andric case TargetOpcode::G_SEXT: 269*5f757f3fSDimitry Andric case TargetOpcode::G_ZEXT: 270*5f757f3fSDimitry Andric case TargetOpcode::G_SEXTLOAD: 271*5f757f3fSDimitry Andric case TargetOpcode::G_ZEXTLOAD: 272*5f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping, 273*5f757f3fSDimitry Andric NumOperands); 274*5f757f3fSDimitry Andric case TargetOpcode::G_FADD: 275*5f757f3fSDimitry Andric case TargetOpcode::G_FSUB: 276*5f757f3fSDimitry Andric case TargetOpcode::G_FMUL: 277*5f757f3fSDimitry Andric case TargetOpcode::G_FDIV: 278*5f757f3fSDimitry Andric case TargetOpcode::G_FABS: 279*5f757f3fSDimitry Andric case TargetOpcode::G_FNEG: 280*5f757f3fSDimitry Andric case TargetOpcode::G_FSQRT: 281*5f757f3fSDimitry Andric case TargetOpcode::G_FMAXNUM: 282*5f757f3fSDimitry Andric case TargetOpcode::G_FMINNUM: { 283*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 284*5f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, 285*5f757f3fSDimitry Andric getFPValueMapping(Ty.getSizeInBits()), 286*5f757f3fSDimitry Andric NumOperands); 287*5f757f3fSDimitry Andric } 288*5f757f3fSDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 289*5f757f3fSDimitry Andric Register Dst = MI.getOperand(0).getReg(); 290*5f757f3fSDimitry Andric auto Mapping = GPRValueMapping; 291*5f757f3fSDimitry Andric // FIXME: May need to do a better job determining when to use FPRB. 292*5f757f3fSDimitry Andric // For example, the look through COPY case: 293*5f757f3fSDimitry Andric // %0:_(s32) = G_IMPLICIT_DEF 294*5f757f3fSDimitry Andric // %1:_(s32) = COPY %0 295*5f757f3fSDimitry Andric // $f10_d = COPY %1(s32) 296*5f757f3fSDimitry Andric if (anyUseOnlyUseFP(Dst, MRI, TRI)) 297*5f757f3fSDimitry Andric Mapping = getFPValueMapping(MRI.getType(Dst).getSizeInBits()); 298*5f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping, 299*5f757f3fSDimitry Andric NumOperands); 300*5f757f3fSDimitry Andric } 301*5f757f3fSDimitry Andric } 302*5f757f3fSDimitry Andric 303*5f757f3fSDimitry Andric SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands); 304*5f757f3fSDimitry Andric 305*5f757f3fSDimitry Andric switch (Opc) { 306*5f757f3fSDimitry Andric case TargetOpcode::G_LOAD: { 307*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 308*5f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 309*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 310*5f757f3fSDimitry Andric // Use FPR64 for s64 loads on rv32. 311*5f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 312*5f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 313*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 314*5f757f3fSDimitry Andric break; 315*5f757f3fSDimitry Andric } 316*5f757f3fSDimitry Andric 317*5f757f3fSDimitry Andric // Check if that load feeds fp instructions. 318*5f757f3fSDimitry Andric // In that case, we want the default mapping to be on FPR 319*5f757f3fSDimitry Andric // instead of blind map every scalar to GPR. 320*5f757f3fSDimitry Andric if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) 321*5f757f3fSDimitry Andric // If we have at least one direct use in a FP instruction, 322*5f757f3fSDimitry Andric // assume this was a floating point load in the IR. If it was 323*5f757f3fSDimitry Andric // not, we would have had a bitcast before reaching that 324*5f757f3fSDimitry Andric // instruction. 325*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 326*5f757f3fSDimitry Andric 327*5f757f3fSDimitry Andric break; 328*5f757f3fSDimitry Andric } 329*5f757f3fSDimitry Andric case TargetOpcode::G_STORE: { 330*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 331*5f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 332*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 333*5f757f3fSDimitry Andric // Use FPR64 for s64 stores on rv32. 334*5f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 335*5f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 336*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 337*5f757f3fSDimitry Andric break; 338*5f757f3fSDimitry Andric } 339*5f757f3fSDimitry Andric 340*5f757f3fSDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg()); 341*5f757f3fSDimitry Andric if (onlyDefinesFP(*DefMI, MRI, TRI)) 342*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 343*5f757f3fSDimitry Andric break; 344*5f757f3fSDimitry Andric } 345*5f757f3fSDimitry Andric case TargetOpcode::G_SELECT: { 346*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 347*5f757f3fSDimitry Andric 348*5f757f3fSDimitry Andric // Try to minimize the number of copies. If we have more floating point 349*5f757f3fSDimitry Andric // constrained values than not, then we'll put everything on FPR. Otherwise, 350*5f757f3fSDimitry Andric // everything has to be on GPR. 351*5f757f3fSDimitry Andric unsigned NumFP = 0; 352*5f757f3fSDimitry Andric 353*5f757f3fSDimitry Andric // Use FPR64 for s64 select on rv32. 354*5f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 355*5f757f3fSDimitry Andric NumFP = 3; 356*5f757f3fSDimitry Andric } else { 357*5f757f3fSDimitry Andric // Check if the uses of the result always produce floating point values. 358*5f757f3fSDimitry Andric // 359*5f757f3fSDimitry Andric // For example: 360*5f757f3fSDimitry Andric // 361*5f757f3fSDimitry Andric // %z = G_SELECT %cond %x %y 362*5f757f3fSDimitry Andric // fpr = G_FOO %z ... 363*5f757f3fSDimitry Andric if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 364*5f757f3fSDimitry Andric [&](const MachineInstr &UseMI) { 365*5f757f3fSDimitry Andric return onlyUsesFP(UseMI, MRI, TRI); 366*5f757f3fSDimitry Andric })) 367*5f757f3fSDimitry Andric ++NumFP; 368*5f757f3fSDimitry Andric 369*5f757f3fSDimitry Andric // Check if the defs of the source values always produce floating point 370*5f757f3fSDimitry Andric // values. 371*5f757f3fSDimitry Andric // 372*5f757f3fSDimitry Andric // For example: 373*5f757f3fSDimitry Andric // 374*5f757f3fSDimitry Andric // %x = G_SOMETHING_ALWAYS_FLOAT %a ... 375*5f757f3fSDimitry Andric // %z = G_SELECT %cond %x %y 376*5f757f3fSDimitry Andric // 377*5f757f3fSDimitry Andric // Also check whether or not the sources have already been decided to be 378*5f757f3fSDimitry Andric // FPR. Keep track of this. 379*5f757f3fSDimitry Andric // 380*5f757f3fSDimitry Andric // This doesn't check the condition, since the condition is always an 381*5f757f3fSDimitry Andric // integer. 382*5f757f3fSDimitry Andric for (unsigned Idx = 2; Idx < 4; ++Idx) { 383*5f757f3fSDimitry Andric Register VReg = MI.getOperand(Idx).getReg(); 384*5f757f3fSDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(VReg); 385*5f757f3fSDimitry Andric if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank || 386*5f757f3fSDimitry Andric onlyDefinesFP(*DefMI, MRI, TRI)) 387*5f757f3fSDimitry Andric ++NumFP; 388*5f757f3fSDimitry Andric } 389*5f757f3fSDimitry Andric } 390*5f757f3fSDimitry Andric 391*5f757f3fSDimitry Andric // Condition operand is always GPR. 392*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 393*5f757f3fSDimitry Andric 394*5f757f3fSDimitry Andric const ValueMapping *Mapping = GPRValueMapping; 395*5f757f3fSDimitry Andric if (NumFP >= 2) 396*5f757f3fSDimitry Andric Mapping = getFPValueMapping(Ty.getSizeInBits()); 397*5f757f3fSDimitry Andric 398*5f757f3fSDimitry Andric OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping; 399*5f757f3fSDimitry Andric break; 400*5f757f3fSDimitry Andric } 401*5f757f3fSDimitry Andric case TargetOpcode::G_FPTOSI: 402*5f757f3fSDimitry Andric case TargetOpcode::G_FPTOUI: 403*5f757f3fSDimitry Andric case RISCV::G_FCLASS: { 404*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(1).getReg()); 405*5f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 406*5f757f3fSDimitry Andric OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits()); 407*5f757f3fSDimitry Andric break; 408*5f757f3fSDimitry Andric } 409*5f757f3fSDimitry Andric case TargetOpcode::G_SITOFP: 410*5f757f3fSDimitry Andric case TargetOpcode::G_UITOFP: { 411*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 412*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 413*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 414*5f757f3fSDimitry Andric break; 415*5f757f3fSDimitry Andric } 416*5f757f3fSDimitry Andric case TargetOpcode::G_FCMP: { 417*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(2).getReg()); 418*5f757f3fSDimitry Andric 419*5f757f3fSDimitry Andric unsigned Size = Ty.getSizeInBits(); 420*5f757f3fSDimitry Andric assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 421*5f757f3fSDimitry Andric 422*5f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 423*5f757f3fSDimitry Andric OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size); 424*5f757f3fSDimitry Andric break; 425*5f757f3fSDimitry Andric } 426*5f757f3fSDimitry Andric case TargetOpcode::G_MERGE_VALUES: { 427*5f757f3fSDimitry Andric // Use FPR64 for s64 merge on rv32. 428*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 429*5f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 430*5f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 431*5f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 432*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 433*5f757f3fSDimitry Andric OpdsMapping[2] = GPRValueMapping; 434*5f757f3fSDimitry Andric } 435*5f757f3fSDimitry Andric break; 436*5f757f3fSDimitry Andric } 437*5f757f3fSDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: { 438*5f757f3fSDimitry Andric // Use FPR64 for s64 unmerge on rv32. 439*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(2).getReg()); 440*5f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 441*5f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 442*5f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 443*5f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 444*5f757f3fSDimitry Andric OpdsMapping[2] = getFPValueMapping(Ty.getSizeInBits()); 445*5f757f3fSDimitry Andric } 446*5f757f3fSDimitry Andric break; 447*5f757f3fSDimitry Andric } 448*5f757f3fSDimitry Andric default: 449*5f757f3fSDimitry Andric // By default map all scalars to GPR. 450*5f757f3fSDimitry Andric for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 451*5f757f3fSDimitry Andric auto &MO = MI.getOperand(Idx); 452*5f757f3fSDimitry Andric if (!MO.isReg() || !MO.getReg()) 453*5f757f3fSDimitry Andric continue; 454*5f757f3fSDimitry Andric LLT Ty = MRI.getType(MO.getReg()); 455*5f757f3fSDimitry Andric if (!Ty.isValid()) 456*5f757f3fSDimitry Andric continue; 457*5f757f3fSDimitry Andric 458*5f757f3fSDimitry Andric if (isPreISelGenericFloatingPointOpcode(Opc)) 459*5f757f3fSDimitry Andric OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits()); 460*5f757f3fSDimitry Andric else 461*5f757f3fSDimitry Andric OpdsMapping[Idx] = GPRValueMapping; 462*5f757f3fSDimitry Andric } 463*5f757f3fSDimitry Andric break; 464*5f757f3fSDimitry Andric } 465*5f757f3fSDimitry Andric 466*5f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, 467*5f757f3fSDimitry Andric getOperandsMapping(OpdsMapping), NumOperands); 468*5f757f3fSDimitry Andric } 469