xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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