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" 155f757f3fSDimitry Andric #include "RISCVSubtarget.h" 16*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 17bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 18bdd1243dSDimitry Andric #include "llvm/CodeGen/RegisterBank.h" 19bdd1243dSDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 20bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric #define GET_TARGET_REGBANK_IMPL 23bdd1243dSDimitry Andric #include "RISCVGenRegisterBank.inc" 24bdd1243dSDimitry Andric 255f757f3fSDimitry Andric namespace llvm { 265f757f3fSDimitry Andric namespace RISCV { 275f757f3fSDimitry Andric 285f757f3fSDimitry Andric const RegisterBankInfo::PartialMapping PartMappings[] = { 29*0fca6ea1SDimitry Andric // clang-format off 305f757f3fSDimitry Andric {0, 32, GPRBRegBank}, 315f757f3fSDimitry Andric {0, 64, GPRBRegBank}, 32*0fca6ea1SDimitry Andric {0, 16, FPRBRegBank}, 335f757f3fSDimitry Andric {0, 32, FPRBRegBank}, 345f757f3fSDimitry Andric {0, 64, FPRBRegBank}, 35*0fca6ea1SDimitry Andric {0, 64, VRBRegBank}, 36*0fca6ea1SDimitry Andric {0, 128, VRBRegBank}, 37*0fca6ea1SDimitry Andric {0, 256, VRBRegBank}, 38*0fca6ea1SDimitry Andric {0, 512, VRBRegBank}, 39*0fca6ea1SDimitry Andric // clang-format on 405f757f3fSDimitry Andric }; 415f757f3fSDimitry Andric 425f757f3fSDimitry Andric enum PartialMappingIdx { 435f757f3fSDimitry Andric PMI_GPRB32 = 0, 445f757f3fSDimitry Andric PMI_GPRB64 = 1, 45*0fca6ea1SDimitry Andric PMI_FPRB16 = 2, 46*0fca6ea1SDimitry Andric PMI_FPRB32 = 3, 47*0fca6ea1SDimitry Andric PMI_FPRB64 = 4, 48*0fca6ea1SDimitry Andric PMI_VRB64 = 5, 49*0fca6ea1SDimitry Andric PMI_VRB128 = 6, 50*0fca6ea1SDimitry Andric PMI_VRB256 = 7, 51*0fca6ea1SDimitry Andric PMI_VRB512 = 8, 525f757f3fSDimitry Andric }; 535f757f3fSDimitry Andric 545f757f3fSDimitry Andric const RegisterBankInfo::ValueMapping ValueMappings[] = { 555f757f3fSDimitry Andric // Invalid value mapping. 565f757f3fSDimitry Andric {nullptr, 0}, 575f757f3fSDimitry Andric // Maximum 3 GPR operands; 32 bit. 585f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 595f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 605f757f3fSDimitry Andric {&PartMappings[PMI_GPRB32], 1}, 615f757f3fSDimitry Andric // Maximum 3 GPR operands; 64 bit. 625f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 635f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 645f757f3fSDimitry Andric {&PartMappings[PMI_GPRB64], 1}, 65*0fca6ea1SDimitry Andric // Maximum 3 FPR operands; 16 bit. 66*0fca6ea1SDimitry Andric {&PartMappings[PMI_FPRB16], 1}, 67*0fca6ea1SDimitry Andric {&PartMappings[PMI_FPRB16], 1}, 68*0fca6ea1SDimitry Andric {&PartMappings[PMI_FPRB16], 1}, 695f757f3fSDimitry Andric // Maximum 3 FPR operands; 32 bit. 705f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 715f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 725f757f3fSDimitry Andric {&PartMappings[PMI_FPRB32], 1}, 735f757f3fSDimitry Andric // Maximum 3 FPR operands; 64 bit. 745f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 755f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 765f757f3fSDimitry Andric {&PartMappings[PMI_FPRB64], 1}, 77*0fca6ea1SDimitry Andric // Maximum 3 VR LMUL={1, MF2, MF4, MF8} operands. 78*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB64], 1}, 79*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB64], 1}, 80*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB64], 1}, 81*0fca6ea1SDimitry Andric // Maximum 3 VR LMUL=2 operands. 82*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB128], 1}, 83*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB128], 1}, 84*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB128], 1}, 85*0fca6ea1SDimitry Andric // Maximum 3 VR LMUL=4 operands. 86*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB256], 1}, 87*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB256], 1}, 88*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB256], 1}, 89*0fca6ea1SDimitry Andric // Maximum 3 VR LMUL=8 operands. 90*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB512], 1}, 91*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB512], 1}, 92*0fca6ea1SDimitry Andric {&PartMappings[PMI_VRB512], 1}, 935f757f3fSDimitry Andric }; 945f757f3fSDimitry Andric 955f757f3fSDimitry Andric enum ValueMappingIdx { 965f757f3fSDimitry Andric InvalidIdx = 0, 975f757f3fSDimitry Andric GPRB32Idx = 1, 985f757f3fSDimitry Andric GPRB64Idx = 4, 99*0fca6ea1SDimitry Andric FPRB16Idx = 7, 100*0fca6ea1SDimitry Andric FPRB32Idx = 10, 101*0fca6ea1SDimitry Andric FPRB64Idx = 13, 102*0fca6ea1SDimitry Andric VRB64Idx = 16, 103*0fca6ea1SDimitry Andric VRB128Idx = 19, 104*0fca6ea1SDimitry Andric VRB256Idx = 22, 105*0fca6ea1SDimitry Andric VRB512Idx = 25, 1065f757f3fSDimitry Andric }; 1075f757f3fSDimitry Andric } // namespace RISCV 1085f757f3fSDimitry Andric } // namespace llvm 1095f757f3fSDimitry Andric 110bdd1243dSDimitry Andric using namespace llvm; 111bdd1243dSDimitry Andric 11206c3fb27SDimitry Andric RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode) 11306c3fb27SDimitry Andric : RISCVGenRegisterBankInfo(HwMode) {} 1145f757f3fSDimitry Andric 1155f757f3fSDimitry Andric const RegisterBank & 1165f757f3fSDimitry Andric RISCVRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 1175f757f3fSDimitry Andric LLT Ty) const { 1185f757f3fSDimitry Andric switch (RC.getID()) { 1195f757f3fSDimitry Andric default: 1205f757f3fSDimitry Andric llvm_unreachable("Register class not supported"); 1215f757f3fSDimitry Andric case RISCV::GPRRegClassID: 1225f757f3fSDimitry Andric case RISCV::GPRF16RegClassID: 1235f757f3fSDimitry Andric case RISCV::GPRF32RegClassID: 1245f757f3fSDimitry Andric case RISCV::GPRNoX0RegClassID: 1255f757f3fSDimitry Andric case RISCV::GPRNoX0X2RegClassID: 1265f757f3fSDimitry Andric case RISCV::GPRJALRRegClassID: 127*0fca6ea1SDimitry Andric case RISCV::GPRJALRNonX7RegClassID: 1285f757f3fSDimitry Andric case RISCV::GPRTCRegClassID: 129*0fca6ea1SDimitry Andric case RISCV::GPRTCNonX7RegClassID: 1305f757f3fSDimitry Andric case RISCV::GPRC_and_GPRTCRegClassID: 1315f757f3fSDimitry Andric case RISCV::GPRCRegClassID: 1325f757f3fSDimitry Andric case RISCV::GPRC_and_SR07RegClassID: 1335f757f3fSDimitry Andric case RISCV::SR07RegClassID: 1345f757f3fSDimitry Andric case RISCV::SPRegClassID: 1355f757f3fSDimitry Andric case RISCV::GPRX0RegClassID: 1365f757f3fSDimitry Andric return getRegBank(RISCV::GPRBRegBankID); 1375f757f3fSDimitry Andric case RISCV::FPR64RegClassID: 1385f757f3fSDimitry Andric case RISCV::FPR16RegClassID: 1395f757f3fSDimitry Andric case RISCV::FPR32RegClassID: 1405f757f3fSDimitry Andric case RISCV::FPR64CRegClassID: 1415f757f3fSDimitry Andric case RISCV::FPR32CRegClassID: 1425f757f3fSDimitry Andric return getRegBank(RISCV::FPRBRegBankID); 1435f757f3fSDimitry Andric case RISCV::VMRegClassID: 1445f757f3fSDimitry Andric case RISCV::VRRegClassID: 1455f757f3fSDimitry Andric case RISCV::VRNoV0RegClassID: 1465f757f3fSDimitry Andric case RISCV::VRM2RegClassID: 1475f757f3fSDimitry Andric case RISCV::VRM2NoV0RegClassID: 1485f757f3fSDimitry Andric case RISCV::VRM4RegClassID: 1495f757f3fSDimitry Andric case RISCV::VRM4NoV0RegClassID: 1505f757f3fSDimitry Andric case RISCV::VMV0RegClassID: 1515f757f3fSDimitry Andric case RISCV::VRM2_with_sub_vrm1_0_in_VMV0RegClassID: 1525f757f3fSDimitry Andric case RISCV::VRM4_with_sub_vrm1_0_in_VMV0RegClassID: 1535f757f3fSDimitry Andric case RISCV::VRM8RegClassID: 1545f757f3fSDimitry Andric case RISCV::VRM8NoV0RegClassID: 1555f757f3fSDimitry Andric case RISCV::VRM8_with_sub_vrm1_0_in_VMV0RegClassID: 1565f757f3fSDimitry Andric return getRegBank(RISCV::VRBRegBankID); 1575f757f3fSDimitry Andric } 1585f757f3fSDimitry Andric } 1595f757f3fSDimitry Andric 1605f757f3fSDimitry Andric static const RegisterBankInfo::ValueMapping *getFPValueMapping(unsigned Size) { 161*0fca6ea1SDimitry Andric unsigned Idx; 162*0fca6ea1SDimitry Andric switch (Size) { 163*0fca6ea1SDimitry Andric default: 164*0fca6ea1SDimitry Andric llvm_unreachable("Unexpected size"); 165*0fca6ea1SDimitry Andric case 16: 166*0fca6ea1SDimitry Andric Idx = RISCV::FPRB16Idx; 167*0fca6ea1SDimitry Andric break; 168*0fca6ea1SDimitry Andric case 32: 169*0fca6ea1SDimitry Andric Idx = RISCV::FPRB32Idx; 170*0fca6ea1SDimitry Andric break; 171*0fca6ea1SDimitry Andric case 64: 172*0fca6ea1SDimitry Andric Idx = RISCV::FPRB64Idx; 173*0fca6ea1SDimitry Andric break; 174*0fca6ea1SDimitry Andric } 1755f757f3fSDimitry Andric return &RISCV::ValueMappings[Idx]; 1765f757f3fSDimitry Andric } 1775f757f3fSDimitry Andric 1785f757f3fSDimitry Andric // TODO: Make this more like AArch64? 1795f757f3fSDimitry Andric bool RISCVRegisterBankInfo::hasFPConstraints( 1805f757f3fSDimitry Andric const MachineInstr &MI, const MachineRegisterInfo &MRI, 1815f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 1825f757f3fSDimitry Andric if (isPreISelGenericFloatingPointOpcode(MI.getOpcode())) 1835f757f3fSDimitry Andric return true; 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric // If we have a copy instruction, we could be feeding floating point 1865f757f3fSDimitry Andric // instructions. 1875f757f3fSDimitry Andric if (MI.getOpcode() != TargetOpcode::COPY) 1885f757f3fSDimitry Andric return false; 1895f757f3fSDimitry Andric 1905f757f3fSDimitry Andric return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) == &RISCV::FPRBRegBank; 1915f757f3fSDimitry Andric } 1925f757f3fSDimitry Andric 1935f757f3fSDimitry Andric bool RISCVRegisterBankInfo::onlyUsesFP(const MachineInstr &MI, 1945f757f3fSDimitry Andric const MachineRegisterInfo &MRI, 1955f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 1965f757f3fSDimitry Andric switch (MI.getOpcode()) { 1975f757f3fSDimitry Andric case TargetOpcode::G_FPTOSI: 1985f757f3fSDimitry Andric case TargetOpcode::G_FPTOUI: 1995f757f3fSDimitry Andric case TargetOpcode::G_FCMP: 2005f757f3fSDimitry Andric return true; 2015f757f3fSDimitry Andric default: 2025f757f3fSDimitry Andric break; 2035f757f3fSDimitry Andric } 2045f757f3fSDimitry Andric 2055f757f3fSDimitry Andric return hasFPConstraints(MI, MRI, TRI); 2065f757f3fSDimitry Andric } 2075f757f3fSDimitry Andric 2085f757f3fSDimitry Andric bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, 2095f757f3fSDimitry Andric const MachineRegisterInfo &MRI, 2105f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 2115f757f3fSDimitry Andric switch (MI.getOpcode()) { 2125f757f3fSDimitry Andric case TargetOpcode::G_SITOFP: 2135f757f3fSDimitry Andric case TargetOpcode::G_UITOFP: 2145f757f3fSDimitry Andric return true; 2155f757f3fSDimitry Andric default: 2165f757f3fSDimitry Andric break; 2175f757f3fSDimitry Andric } 2185f757f3fSDimitry Andric 2195f757f3fSDimitry Andric return hasFPConstraints(MI, MRI, TRI); 2205f757f3fSDimitry Andric } 2215f757f3fSDimitry Andric 2225f757f3fSDimitry Andric bool RISCVRegisterBankInfo::anyUseOnlyUseFP( 2235f757f3fSDimitry Andric Register Def, const MachineRegisterInfo &MRI, 2245f757f3fSDimitry Andric const TargetRegisterInfo &TRI) const { 2255f757f3fSDimitry Andric return any_of( 2265f757f3fSDimitry Andric MRI.use_nodbg_instructions(Def), 2275f757f3fSDimitry Andric [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); }); 2285f757f3fSDimitry Andric } 2295f757f3fSDimitry Andric 230*0fca6ea1SDimitry Andric static const RegisterBankInfo::ValueMapping *getVRBValueMapping(unsigned Size) { 231*0fca6ea1SDimitry Andric unsigned Idx; 232*0fca6ea1SDimitry Andric 233*0fca6ea1SDimitry Andric if (Size <= 64) 234*0fca6ea1SDimitry Andric Idx = RISCV::VRB64Idx; 235*0fca6ea1SDimitry Andric else if (Size == 128) 236*0fca6ea1SDimitry Andric Idx = RISCV::VRB128Idx; 237*0fca6ea1SDimitry Andric else if (Size == 256) 238*0fca6ea1SDimitry Andric Idx = RISCV::VRB256Idx; 239*0fca6ea1SDimitry Andric else if (Size == 512) 240*0fca6ea1SDimitry Andric Idx = RISCV::VRB512Idx; 241*0fca6ea1SDimitry Andric else 242*0fca6ea1SDimitry Andric llvm::report_fatal_error("Invalid Size"); 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric return &RISCV::ValueMappings[Idx]; 245*0fca6ea1SDimitry Andric } 246*0fca6ea1SDimitry Andric 2475f757f3fSDimitry Andric const RegisterBankInfo::InstructionMapping & 2485f757f3fSDimitry Andric RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 2495f757f3fSDimitry Andric const unsigned Opc = MI.getOpcode(); 2505f757f3fSDimitry Andric 2515f757f3fSDimitry Andric // Try the default logic for non-generic instructions that are either copies 2525f757f3fSDimitry Andric // or already have some operands assigned to banks. 2535f757f3fSDimitry Andric if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 2545f757f3fSDimitry Andric const InstructionMapping &Mapping = getInstrMappingImpl(MI); 2555f757f3fSDimitry Andric if (Mapping.isValid()) 2565f757f3fSDimitry Andric return Mapping; 2575f757f3fSDimitry Andric } 2585f757f3fSDimitry Andric 2595f757f3fSDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 2605f757f3fSDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2615f757f3fSDimitry Andric const TargetSubtargetInfo &STI = MF.getSubtarget(); 2625f757f3fSDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 2635f757f3fSDimitry Andric 2645f757f3fSDimitry Andric unsigned GPRSize = getMaximumSize(RISCV::GPRBRegBankID); 2655f757f3fSDimitry Andric assert((GPRSize == 32 || GPRSize == 64) && "Unexpected GPR size"); 2665f757f3fSDimitry Andric 2675f757f3fSDimitry Andric unsigned NumOperands = MI.getNumOperands(); 2685f757f3fSDimitry Andric const ValueMapping *GPRValueMapping = 2695f757f3fSDimitry Andric &RISCV::ValueMappings[GPRSize == 64 ? RISCV::GPRB64Idx 2705f757f3fSDimitry Andric : RISCV::GPRB32Idx]; 2715f757f3fSDimitry Andric 2725f757f3fSDimitry Andric switch (Opc) { 2735f757f3fSDimitry Andric case TargetOpcode::G_ADD: 2745f757f3fSDimitry Andric case TargetOpcode::G_SUB: 2755f757f3fSDimitry Andric case TargetOpcode::G_SHL: 2765f757f3fSDimitry Andric case TargetOpcode::G_ASHR: 2775f757f3fSDimitry Andric case TargetOpcode::G_LSHR: 2785f757f3fSDimitry Andric case TargetOpcode::G_AND: 2795f757f3fSDimitry Andric case TargetOpcode::G_OR: 2805f757f3fSDimitry Andric case TargetOpcode::G_XOR: 2815f757f3fSDimitry Andric case TargetOpcode::G_MUL: 2825f757f3fSDimitry Andric case TargetOpcode::G_SDIV: 2835f757f3fSDimitry Andric case TargetOpcode::G_SREM: 2845f757f3fSDimitry Andric case TargetOpcode::G_SMULH: 2855f757f3fSDimitry Andric case TargetOpcode::G_SMAX: 2865f757f3fSDimitry Andric case TargetOpcode::G_SMIN: 2875f757f3fSDimitry Andric case TargetOpcode::G_UDIV: 2885f757f3fSDimitry Andric case TargetOpcode::G_UREM: 2895f757f3fSDimitry Andric case TargetOpcode::G_UMULH: 2905f757f3fSDimitry Andric case TargetOpcode::G_UMAX: 2915f757f3fSDimitry Andric case TargetOpcode::G_UMIN: 2925f757f3fSDimitry Andric case TargetOpcode::G_PTR_ADD: 2935f757f3fSDimitry Andric case TargetOpcode::G_PTRTOINT: 2945f757f3fSDimitry Andric case TargetOpcode::G_INTTOPTR: 2955f757f3fSDimitry Andric case TargetOpcode::G_FADD: 2965f757f3fSDimitry Andric case TargetOpcode::G_FSUB: 2975f757f3fSDimitry Andric case TargetOpcode::G_FMUL: 2985f757f3fSDimitry Andric case TargetOpcode::G_FDIV: 2995f757f3fSDimitry Andric case TargetOpcode::G_FABS: 3005f757f3fSDimitry Andric case TargetOpcode::G_FNEG: 3015f757f3fSDimitry Andric case TargetOpcode::G_FSQRT: 3025f757f3fSDimitry Andric case TargetOpcode::G_FMAXNUM: 3035f757f3fSDimitry Andric case TargetOpcode::G_FMINNUM: { 3045f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 305*0fca6ea1SDimitry Andric TypeSize Size = Ty.getSizeInBits(); 306*0fca6ea1SDimitry Andric 307*0fca6ea1SDimitry Andric const ValueMapping *Mapping; 308*0fca6ea1SDimitry Andric if (Ty.isVector()) 309*0fca6ea1SDimitry Andric Mapping = getVRBValueMapping(Size.getKnownMinValue()); 310*0fca6ea1SDimitry Andric else if (isPreISelGenericFloatingPointOpcode(Opc)) 311*0fca6ea1SDimitry Andric Mapping = getFPValueMapping(Size.getFixedValue()); 312*0fca6ea1SDimitry Andric else 313*0fca6ea1SDimitry Andric Mapping = GPRValueMapping; 314*0fca6ea1SDimitry Andric 315*0fca6ea1SDimitry Andric #ifndef NDEBUG 316*0fca6ea1SDimitry Andric // Make sure all the operands are using similar size and type. 317*0fca6ea1SDimitry Andric for (unsigned Idx = 1; Idx != NumOperands; ++Idx) { 318*0fca6ea1SDimitry Andric LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg()); 319*0fca6ea1SDimitry Andric assert(Ty.isVector() == OpTy.isVector() && 320*0fca6ea1SDimitry Andric "Operand has incompatible type"); 321*0fca6ea1SDimitry Andric // Don't check size for GPR. 322*0fca6ea1SDimitry Andric if (OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc)) 323*0fca6ea1SDimitry Andric assert(Size == OpTy.getSizeInBits() && "Operand has incompatible size"); 3245f757f3fSDimitry Andric } 325*0fca6ea1SDimitry Andric #endif // End NDEBUG 326*0fca6ea1SDimitry Andric 327*0fca6ea1SDimitry Andric return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 328*0fca6ea1SDimitry Andric } 329*0fca6ea1SDimitry Andric case TargetOpcode::G_SEXTLOAD: 330*0fca6ea1SDimitry Andric case TargetOpcode::G_ZEXTLOAD: 331*0fca6ea1SDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping, 332*0fca6ea1SDimitry Andric NumOperands); 3335f757f3fSDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 3345f757f3fSDimitry Andric Register Dst = MI.getOperand(0).getReg(); 335*0fca6ea1SDimitry Andric LLT DstTy = MRI.getType(Dst); 336*0fca6ea1SDimitry Andric unsigned DstMinSize = DstTy.getSizeInBits().getKnownMinValue(); 3375f757f3fSDimitry Andric auto Mapping = GPRValueMapping; 3385f757f3fSDimitry Andric // FIXME: May need to do a better job determining when to use FPRB. 3395f757f3fSDimitry Andric // For example, the look through COPY case: 3405f757f3fSDimitry Andric // %0:_(s32) = G_IMPLICIT_DEF 3415f757f3fSDimitry Andric // %1:_(s32) = COPY %0 3425f757f3fSDimitry Andric // $f10_d = COPY %1(s32) 343*0fca6ea1SDimitry Andric if (DstTy.isVector()) 344*0fca6ea1SDimitry Andric Mapping = getVRBValueMapping(DstMinSize); 345*0fca6ea1SDimitry Andric else if (anyUseOnlyUseFP(Dst, MRI, TRI)) 346*0fca6ea1SDimitry Andric Mapping = getFPValueMapping(DstMinSize); 347*0fca6ea1SDimitry Andric 3485f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping, 3495f757f3fSDimitry Andric NumOperands); 3505f757f3fSDimitry Andric } 3515f757f3fSDimitry Andric } 3525f757f3fSDimitry Andric 3535f757f3fSDimitry Andric SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands); 3545f757f3fSDimitry Andric 3555f757f3fSDimitry Andric switch (Opc) { 3565f757f3fSDimitry Andric case TargetOpcode::G_LOAD: { 3575f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3585f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 3595f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 3605f757f3fSDimitry Andric // Use FPR64 for s64 loads on rv32. 3615f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 3625f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 3635f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 3645f757f3fSDimitry Andric break; 3655f757f3fSDimitry Andric } 3665f757f3fSDimitry Andric 3675f757f3fSDimitry Andric // Check if that load feeds fp instructions. 3685f757f3fSDimitry Andric // In that case, we want the default mapping to be on FPR 3695f757f3fSDimitry Andric // instead of blind map every scalar to GPR. 3705f757f3fSDimitry Andric if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) 3715f757f3fSDimitry Andric // If we have at least one direct use in a FP instruction, 3725f757f3fSDimitry Andric // assume this was a floating point load in the IR. If it was 3735f757f3fSDimitry Andric // not, we would have had a bitcast before reaching that 3745f757f3fSDimitry Andric // instruction. 3755f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 3765f757f3fSDimitry Andric 3775f757f3fSDimitry Andric break; 3785f757f3fSDimitry Andric } 3795f757f3fSDimitry Andric case TargetOpcode::G_STORE: { 3805f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3815f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 3825f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 3835f757f3fSDimitry Andric // Use FPR64 for s64 stores on rv32. 3845f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 3855f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 3865f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 3875f757f3fSDimitry Andric break; 3885f757f3fSDimitry Andric } 3895f757f3fSDimitry Andric 3905f757f3fSDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg()); 3915f757f3fSDimitry Andric if (onlyDefinesFP(*DefMI, MRI, TRI)) 3925f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 3935f757f3fSDimitry Andric break; 3945f757f3fSDimitry Andric } 3955f757f3fSDimitry Andric case TargetOpcode::G_SELECT: { 3965f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3975f757f3fSDimitry Andric 398*0fca6ea1SDimitry Andric if (Ty.isVector()) { 399*0fca6ea1SDimitry Andric auto &Sel = cast<GSelect>(MI); 400*0fca6ea1SDimitry Andric LLT TestTy = MRI.getType(Sel.getCondReg()); 401*0fca6ea1SDimitry Andric assert(TestTy.isVector() && "Unexpected condition argument type"); 402*0fca6ea1SDimitry Andric OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = 403*0fca6ea1SDimitry Andric getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue()); 404*0fca6ea1SDimitry Andric OpdsMapping[1] = 405*0fca6ea1SDimitry Andric getVRBValueMapping(TestTy.getSizeInBits().getKnownMinValue()); 406*0fca6ea1SDimitry Andric break; 407*0fca6ea1SDimitry Andric } 408*0fca6ea1SDimitry Andric 4095f757f3fSDimitry Andric // Try to minimize the number of copies. If we have more floating point 4105f757f3fSDimitry Andric // constrained values than not, then we'll put everything on FPR. Otherwise, 4115f757f3fSDimitry Andric // everything has to be on GPR. 4125f757f3fSDimitry Andric unsigned NumFP = 0; 4135f757f3fSDimitry Andric 4145f757f3fSDimitry Andric // Use FPR64 for s64 select on rv32. 4155f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 4165f757f3fSDimitry Andric NumFP = 3; 4175f757f3fSDimitry Andric } else { 4185f757f3fSDimitry Andric // Check if the uses of the result always produce floating point values. 4195f757f3fSDimitry Andric // 4205f757f3fSDimitry Andric // For example: 4215f757f3fSDimitry Andric // 4225f757f3fSDimitry Andric // %z = G_SELECT %cond %x %y 4235f757f3fSDimitry Andric // fpr = G_FOO %z ... 4245f757f3fSDimitry Andric if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 4255f757f3fSDimitry Andric [&](const MachineInstr &UseMI) { 4265f757f3fSDimitry Andric return onlyUsesFP(UseMI, MRI, TRI); 4275f757f3fSDimitry Andric })) 4285f757f3fSDimitry Andric ++NumFP; 4295f757f3fSDimitry Andric 4305f757f3fSDimitry Andric // Check if the defs of the source values always produce floating point 4315f757f3fSDimitry Andric // values. 4325f757f3fSDimitry Andric // 4335f757f3fSDimitry Andric // For example: 4345f757f3fSDimitry Andric // 4355f757f3fSDimitry Andric // %x = G_SOMETHING_ALWAYS_FLOAT %a ... 4365f757f3fSDimitry Andric // %z = G_SELECT %cond %x %y 4375f757f3fSDimitry Andric // 4385f757f3fSDimitry Andric // Also check whether or not the sources have already been decided to be 4395f757f3fSDimitry Andric // FPR. Keep track of this. 4405f757f3fSDimitry Andric // 4415f757f3fSDimitry Andric // This doesn't check the condition, since the condition is always an 4425f757f3fSDimitry Andric // integer. 4435f757f3fSDimitry Andric for (unsigned Idx = 2; Idx < 4; ++Idx) { 4445f757f3fSDimitry Andric Register VReg = MI.getOperand(Idx).getReg(); 4455f757f3fSDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(VReg); 4465f757f3fSDimitry Andric if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank || 4475f757f3fSDimitry Andric onlyDefinesFP(*DefMI, MRI, TRI)) 4485f757f3fSDimitry Andric ++NumFP; 4495f757f3fSDimitry Andric } 4505f757f3fSDimitry Andric } 4515f757f3fSDimitry Andric 4525f757f3fSDimitry Andric // Condition operand is always GPR. 4535f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 4545f757f3fSDimitry Andric 4555f757f3fSDimitry Andric const ValueMapping *Mapping = GPRValueMapping; 4565f757f3fSDimitry Andric if (NumFP >= 2) 4575f757f3fSDimitry Andric Mapping = getFPValueMapping(Ty.getSizeInBits()); 4585f757f3fSDimitry Andric 4595f757f3fSDimitry Andric OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping; 4605f757f3fSDimitry Andric break; 4615f757f3fSDimitry Andric } 4625f757f3fSDimitry Andric case TargetOpcode::G_FPTOSI: 4635f757f3fSDimitry Andric case TargetOpcode::G_FPTOUI: 4645f757f3fSDimitry Andric case RISCV::G_FCLASS: { 4655f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(1).getReg()); 4665f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 4675f757f3fSDimitry Andric OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits()); 4685f757f3fSDimitry Andric break; 4695f757f3fSDimitry Andric } 4705f757f3fSDimitry Andric case TargetOpcode::G_SITOFP: 4715f757f3fSDimitry Andric case TargetOpcode::G_UITOFP: { 4725f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 4735f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 4745f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 4755f757f3fSDimitry Andric break; 4765f757f3fSDimitry Andric } 4775f757f3fSDimitry Andric case TargetOpcode::G_FCMP: { 4785f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(2).getReg()); 4795f757f3fSDimitry Andric 4805f757f3fSDimitry Andric unsigned Size = Ty.getSizeInBits(); 4815f757f3fSDimitry Andric 4825f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 4835f757f3fSDimitry Andric OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size); 4845f757f3fSDimitry Andric break; 4855f757f3fSDimitry Andric } 4865f757f3fSDimitry Andric case TargetOpcode::G_MERGE_VALUES: { 4875f757f3fSDimitry Andric // Use FPR64 for s64 merge on rv32. 4885f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 4895f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 4905f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 4915f757f3fSDimitry Andric OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits()); 4925f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 4935f757f3fSDimitry Andric OpdsMapping[2] = GPRValueMapping; 4945f757f3fSDimitry Andric } 4955f757f3fSDimitry Andric break; 4965f757f3fSDimitry Andric } 4975f757f3fSDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: { 4985f757f3fSDimitry Andric // Use FPR64 for s64 unmerge on rv32. 4995f757f3fSDimitry Andric LLT Ty = MRI.getType(MI.getOperand(2).getReg()); 5005f757f3fSDimitry Andric if (GPRSize == 32 && Ty.getSizeInBits() == 64) { 5015f757f3fSDimitry Andric assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD()); 5025f757f3fSDimitry Andric OpdsMapping[0] = GPRValueMapping; 5035f757f3fSDimitry Andric OpdsMapping[1] = GPRValueMapping; 5045f757f3fSDimitry Andric OpdsMapping[2] = getFPValueMapping(Ty.getSizeInBits()); 5055f757f3fSDimitry Andric } 5065f757f3fSDimitry Andric break; 5075f757f3fSDimitry Andric } 5085f757f3fSDimitry Andric default: 5095f757f3fSDimitry Andric // By default map all scalars to GPR. 5105f757f3fSDimitry Andric for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 5115f757f3fSDimitry Andric auto &MO = MI.getOperand(Idx); 5125f757f3fSDimitry Andric if (!MO.isReg() || !MO.getReg()) 5135f757f3fSDimitry Andric continue; 5145f757f3fSDimitry Andric LLT Ty = MRI.getType(MO.getReg()); 5155f757f3fSDimitry Andric if (!Ty.isValid()) 5165f757f3fSDimitry Andric continue; 5175f757f3fSDimitry Andric 518*0fca6ea1SDimitry Andric if (Ty.isVector()) 519*0fca6ea1SDimitry Andric OpdsMapping[Idx] = 520*0fca6ea1SDimitry Andric getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue()); 521*0fca6ea1SDimitry Andric else if (isPreISelGenericFloatingPointOpcode(Opc)) 5225f757f3fSDimitry Andric OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits()); 5235f757f3fSDimitry Andric else 5245f757f3fSDimitry Andric OpdsMapping[Idx] = GPRValueMapping; 5255f757f3fSDimitry Andric } 5265f757f3fSDimitry Andric break; 5275f757f3fSDimitry Andric } 5285f757f3fSDimitry Andric 5295f757f3fSDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, 5305f757f3fSDimitry Andric getOperandsMapping(OpdsMapping), NumOperands); 5315f757f3fSDimitry Andric } 532