xref: /llvm-project/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp (revision de6d0d2de0e2df72bd77f29d27addf13ebfbc997)
14be39288SPhilip Reames //===-- RISCVRegisterBankInfo.cpp -------------------------------*- C++ -*-===//
24be39288SPhilip Reames //
34be39288SPhilip Reames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44be39288SPhilip Reames // See https://llvm.org/LICENSE.txt for license information.
54be39288SPhilip Reames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64be39288SPhilip Reames //
74be39288SPhilip Reames //===----------------------------------------------------------------------===//
84be39288SPhilip Reames /// \file
929463612SCraig Topper /// This file implements the targeting of the RegisterBankInfo class for RISC-V.
104be39288SPhilip Reames /// \todo This should be generated by TableGen.
114be39288SPhilip Reames //===----------------------------------------------------------------------===//
124be39288SPhilip Reames 
134be39288SPhilip Reames #include "RISCVRegisterBankInfo.h"
144be39288SPhilip Reames #include "MCTargetDesc/RISCVMCTargetDesc.h"
15d9320e22SCraig Topper #include "RISCVSubtarget.h"
16973e9dbdSMichael Maitland #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
174be39288SPhilip Reames #include "llvm/CodeGen/MachineRegisterInfo.h"
184be39288SPhilip Reames #include "llvm/CodeGen/RegisterBank.h"
194be39288SPhilip Reames #include "llvm/CodeGen/RegisterBankInfo.h"
204be39288SPhilip Reames #include "llvm/CodeGen/TargetRegisterInfo.h"
214be39288SPhilip Reames 
224be39288SPhilip Reames #define GET_TARGET_REGBANK_IMPL
234be39288SPhilip Reames #include "RISCVGenRegisterBank.inc"
244be39288SPhilip Reames 
25d9320e22SCraig Topper namespace llvm {
26d9320e22SCraig Topper namespace RISCV {
27d9320e22SCraig Topper 
28c4821073SCraig Topper const RegisterBankInfo::PartialMapping PartMappings[] = {
2910c2d5ffSJiahan Xie     // clang-format off
308c53cfd3SCraig Topper     {0, 32, GPRBRegBank},
318c53cfd3SCraig Topper     {0, 64, GPRBRegBank},
32dddef9d1SCraig Topper     {0, 16, FPRBRegBank},
338c53cfd3SCraig Topper     {0, 32, FPRBRegBank},
348c53cfd3SCraig Topper     {0, 64, FPRBRegBank},
3510c2d5ffSJiahan Xie     {0, 64, VRBRegBank},
3610c2d5ffSJiahan Xie     {0, 128, VRBRegBank},
3710c2d5ffSJiahan Xie     {0, 256, VRBRegBank},
3810c2d5ffSJiahan Xie     {0, 512, VRBRegBank},
3910c2d5ffSJiahan Xie     // clang-format on
40d9320e22SCraig Topper };
41d9320e22SCraig Topper 
42d9320e22SCraig Topper enum PartialMappingIdx {
433e606934SCraig Topper   PMI_GPRB32 = 0,
443e606934SCraig Topper   PMI_GPRB64 = 1,
45dddef9d1SCraig Topper   PMI_FPRB16 = 2,
46dddef9d1SCraig Topper   PMI_FPRB32 = 3,
47dddef9d1SCraig Topper   PMI_FPRB64 = 4,
48dddef9d1SCraig Topper   PMI_VRB64 = 5,
49dddef9d1SCraig Topper   PMI_VRB128 = 6,
50dddef9d1SCraig Topper   PMI_VRB256 = 7,
51dddef9d1SCraig Topper   PMI_VRB512 = 8,
52d9320e22SCraig Topper };
53d9320e22SCraig Topper 
54c4821073SCraig Topper const RegisterBankInfo::ValueMapping ValueMappings[] = {
55d9320e22SCraig Topper     // Invalid value mapping.
56d9320e22SCraig Topper     {nullptr, 0},
57d9320e22SCraig Topper     // Maximum 3 GPR operands; 32 bit.
583e606934SCraig Topper     {&PartMappings[PMI_GPRB32], 1},
593e606934SCraig Topper     {&PartMappings[PMI_GPRB32], 1},
603e606934SCraig Topper     {&PartMappings[PMI_GPRB32], 1},
61d9320e22SCraig Topper     // Maximum 3 GPR operands; 64 bit.
623e606934SCraig Topper     {&PartMappings[PMI_GPRB64], 1},
633e606934SCraig Topper     {&PartMappings[PMI_GPRB64], 1},
643e606934SCraig Topper     {&PartMappings[PMI_GPRB64], 1},
65dddef9d1SCraig Topper     // Maximum 3 FPR operands; 16 bit.
66dddef9d1SCraig Topper     {&PartMappings[PMI_FPRB16], 1},
67dddef9d1SCraig Topper     {&PartMappings[PMI_FPRB16], 1},
68dddef9d1SCraig Topper     {&PartMappings[PMI_FPRB16], 1},
69c2b64dfaSCraig Topper     // Maximum 3 FPR operands; 32 bit.
703e606934SCraig Topper     {&PartMappings[PMI_FPRB32], 1},
713e606934SCraig Topper     {&PartMappings[PMI_FPRB32], 1},
723e606934SCraig Topper     {&PartMappings[PMI_FPRB32], 1},
73c2b64dfaSCraig Topper     // Maximum 3 FPR operands; 64 bit.
743e606934SCraig Topper     {&PartMappings[PMI_FPRB64], 1},
753e606934SCraig Topper     {&PartMappings[PMI_FPRB64], 1},
763e606934SCraig Topper     {&PartMappings[PMI_FPRB64], 1},
7710c2d5ffSJiahan Xie     // Maximum 3 VR LMUL={1, MF2, MF4, MF8} operands.
7810c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB64], 1},
7910c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB64], 1},
8010c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB64], 1},
8110c2d5ffSJiahan Xie     // Maximum 3 VR LMUL=2 operands.
8210c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB128], 1},
8310c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB128], 1},
8410c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB128], 1},
8510c2d5ffSJiahan Xie     // Maximum 3 VR LMUL=4 operands.
8610c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB256], 1},
8710c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB256], 1},
8810c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB256], 1},
8910c2d5ffSJiahan Xie     // Maximum 3 VR LMUL=8 operands.
9010c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB512], 1},
9110c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB512], 1},
9210c2d5ffSJiahan Xie     {&PartMappings[PMI_VRB512], 1},
93d9320e22SCraig Topper };
94d9320e22SCraig Topper 
951ffcac1bSCraig Topper enum ValueMappingIdx {
96d9320e22SCraig Topper   InvalidIdx = 0,
973e606934SCraig Topper   GPRB32Idx = 1,
983e606934SCraig Topper   GPRB64Idx = 4,
99dddef9d1SCraig Topper   FPRB16Idx = 7,
100dddef9d1SCraig Topper   FPRB32Idx = 10,
101dddef9d1SCraig Topper   FPRB64Idx = 13,
102dddef9d1SCraig Topper   VRB64Idx = 16,
103dddef9d1SCraig Topper   VRB128Idx = 19,
104dddef9d1SCraig Topper   VRB256Idx = 22,
105dddef9d1SCraig Topper   VRB512Idx = 25,
106d9320e22SCraig Topper };
107d9320e22SCraig Topper } // namespace RISCV
108d9320e22SCraig Topper } // namespace llvm
109d9320e22SCraig Topper 
1104be39288SPhilip Reames using namespace llvm;
1114be39288SPhilip Reames 
112aa7eace8SNitin John Raj RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode)
113aa7eace8SNitin John Raj     : RISCVGenRegisterBankInfo(HwMode) {}
114d9320e22SCraig Topper 
1157ccdad14SCraig Topper static const RegisterBankInfo::ValueMapping *getFPValueMapping(unsigned Size) {
116dddef9d1SCraig Topper   unsigned Idx;
117dddef9d1SCraig Topper   switch (Size) {
118dddef9d1SCraig Topper   default:
119dddef9d1SCraig Topper     llvm_unreachable("Unexpected size");
120dddef9d1SCraig Topper   case 16:
121dddef9d1SCraig Topper     Idx = RISCV::FPRB16Idx;
122dddef9d1SCraig Topper     break;
123dddef9d1SCraig Topper   case 32:
124dddef9d1SCraig Topper     Idx = RISCV::FPRB32Idx;
125dddef9d1SCraig Topper     break;
126dddef9d1SCraig Topper   case 64:
127dddef9d1SCraig Topper     Idx = RISCV::FPRB64Idx;
128dddef9d1SCraig Topper     break;
129dddef9d1SCraig Topper   }
1307ccdad14SCraig Topper   return &RISCV::ValueMappings[Idx];
1317ccdad14SCraig Topper }
1327ccdad14SCraig Topper 
13305300222SCraig Topper // TODO: Make this more like AArch64?
1349e88a207SCraig Topper bool RISCVRegisterBankInfo::hasFPConstraints(
1359e88a207SCraig Topper     const MachineInstr &MI, const MachineRegisterInfo &MRI,
1369e88a207SCraig Topper     const TargetRegisterInfo &TRI) const {
1379e88a207SCraig Topper   if (isPreISelGenericFloatingPointOpcode(MI.getOpcode()))
1389e88a207SCraig Topper     return true;
1399e88a207SCraig Topper 
1409e88a207SCraig Topper   // If we have a copy instruction, we could be feeding floating point
1419e88a207SCraig Topper   // instructions.
1429e88a207SCraig Topper   if (MI.getOpcode() != TargetOpcode::COPY)
1439e88a207SCraig Topper     return false;
1449e88a207SCraig Topper 
1459e88a207SCraig Topper   return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) == &RISCV::FPRBRegBank;
1469e88a207SCraig Topper }
1479e88a207SCraig Topper 
148c44ac52eSCraig Topper bool RISCVRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
149c44ac52eSCraig Topper                                        const MachineRegisterInfo &MRI,
150c44ac52eSCraig Topper                                        const TargetRegisterInfo &TRI) const {
15105300222SCraig Topper   switch (MI.getOpcode()) {
152d3177d8bSCraig Topper   case RISCV::G_FCVT_W_RV64:
153d3177d8bSCraig Topper   case RISCV::G_FCVT_WU_RV64:
154*de6d0d2dSLuke Quinn   case RISCV::G_FCLASS:
15505300222SCraig Topper   case TargetOpcode::G_FPTOSI:
15605300222SCraig Topper   case TargetOpcode::G_FPTOUI:
1579e88a207SCraig Topper   case TargetOpcode::G_FCMP:
15805300222SCraig Topper     return true;
15905300222SCraig Topper   default:
16005300222SCraig Topper     break;
16105300222SCraig Topper   }
16205300222SCraig Topper 
1639e88a207SCraig Topper   return hasFPConstraints(MI, MRI, TRI);
16405300222SCraig Topper }
16505300222SCraig Topper 
166c44ac52eSCraig Topper bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
167c44ac52eSCraig Topper                                           const MachineRegisterInfo &MRI,
168c44ac52eSCraig Topper                                           const TargetRegisterInfo &TRI) const {
16905300222SCraig Topper   switch (MI.getOpcode()) {
17005300222SCraig Topper   case TargetOpcode::G_SITOFP:
17105300222SCraig Topper   case TargetOpcode::G_UITOFP:
17205300222SCraig Topper     return true;
17305300222SCraig Topper   default:
17405300222SCraig Topper     break;
17505300222SCraig Topper   }
17605300222SCraig Topper 
1779e88a207SCraig Topper   return hasFPConstraints(MI, MRI, TRI);
17805300222SCraig Topper }
17905300222SCraig Topper 
1806976dac0SMichael Maitland bool RISCVRegisterBankInfo::anyUseOnlyUseFP(
1816976dac0SMichael Maitland     Register Def, const MachineRegisterInfo &MRI,
1826976dac0SMichael Maitland     const TargetRegisterInfo &TRI) const {
1836976dac0SMichael Maitland   return any_of(
1846976dac0SMichael Maitland       MRI.use_nodbg_instructions(Def),
1856976dac0SMichael Maitland       [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); });
1866976dac0SMichael Maitland }
1876976dac0SMichael Maitland 
18810c2d5ffSJiahan Xie static const RegisterBankInfo::ValueMapping *getVRBValueMapping(unsigned Size) {
18910c2d5ffSJiahan Xie   unsigned Idx;
19010c2d5ffSJiahan Xie 
19110c2d5ffSJiahan Xie   if (Size <= 64)
19210c2d5ffSJiahan Xie     Idx = RISCV::VRB64Idx;
19310c2d5ffSJiahan Xie   else if (Size == 128)
19410c2d5ffSJiahan Xie     Idx = RISCV::VRB128Idx;
19510c2d5ffSJiahan Xie   else if (Size == 256)
19610c2d5ffSJiahan Xie     Idx = RISCV::VRB256Idx;
19710c2d5ffSJiahan Xie   else if (Size == 512)
19810c2d5ffSJiahan Xie     Idx = RISCV::VRB512Idx;
19910c2d5ffSJiahan Xie   else
20010c2d5ffSJiahan Xie     llvm::report_fatal_error("Invalid Size");
20110c2d5ffSJiahan Xie 
20210c2d5ffSJiahan Xie   return &RISCV::ValueMappings[Idx];
20310c2d5ffSJiahan Xie }
20410c2d5ffSJiahan Xie 
205d9320e22SCraig Topper const RegisterBankInfo::InstructionMapping &
206d9320e22SCraig Topper RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
207d9320e22SCraig Topper   const unsigned Opc = MI.getOpcode();
208d9320e22SCraig Topper 
209d9320e22SCraig Topper   // Try the default logic for non-generic instructions that are either copies
210d9320e22SCraig Topper   // or already have some operands assigned to banks.
211d9320e22SCraig Topper   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
212d9320e22SCraig Topper     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
213d9320e22SCraig Topper     if (Mapping.isValid())
214d9320e22SCraig Topper       return Mapping;
215d9320e22SCraig Topper   }
216d9320e22SCraig Topper 
217c2b64dfaSCraig Topper   const MachineFunction &MF = *MI.getParent()->getParent();
218c2b64dfaSCraig Topper   const MachineRegisterInfo &MRI = MF.getRegInfo();
219c44ac52eSCraig Topper   const TargetSubtargetInfo &STI = MF.getSubtarget();
220c44ac52eSCraig Topper   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
221c2b64dfaSCraig Topper 
2228c53cfd3SCraig Topper   unsigned GPRSize = getMaximumSize(RISCV::GPRBRegBankID);
223d9320e22SCraig Topper   assert((GPRSize == 32 || GPRSize == 64) && "Unexpected GPR size");
224d9320e22SCraig Topper 
225d9320e22SCraig Topper   unsigned NumOperands = MI.getNumOperands();
226d9320e22SCraig Topper   const ValueMapping *GPRValueMapping =
2273e606934SCraig Topper       &RISCV::ValueMappings[GPRSize == 64 ? RISCV::GPRB64Idx
2283e606934SCraig Topper                                           : RISCV::GPRB32Idx];
229d9320e22SCraig Topper 
230d9320e22SCraig Topper   switch (Opc) {
231d9320e22SCraig Topper   case TargetOpcode::G_ADD:
232852eb20bSCraig Topper   case TargetOpcode::G_SUB:
233d9320e22SCraig Topper   case TargetOpcode::G_SHL:
234d9320e22SCraig Topper   case TargetOpcode::G_ASHR:
235d9320e22SCraig Topper   case TargetOpcode::G_LSHR:
236d9320e22SCraig Topper   case TargetOpcode::G_AND:
237d9320e22SCraig Topper   case TargetOpcode::G_OR:
238d9320e22SCraig Topper   case TargetOpcode::G_XOR:
239d9320e22SCraig Topper   case TargetOpcode::G_MUL:
240d9320e22SCraig Topper   case TargetOpcode::G_SDIV:
241d9320e22SCraig Topper   case TargetOpcode::G_SREM:
242de17384cSMin-Yih Hsu   case TargetOpcode::G_SMULH:
243028ed612SCraig Topper   case TargetOpcode::G_SMAX:
244028ed612SCraig Topper   case TargetOpcode::G_SMIN:
245d9320e22SCraig Topper   case TargetOpcode::G_UDIV:
246d9320e22SCraig Topper   case TargetOpcode::G_UREM:
247d9320e22SCraig Topper   case TargetOpcode::G_UMULH:
248028ed612SCraig Topper   case TargetOpcode::G_UMAX:
249028ed612SCraig Topper   case TargetOpcode::G_UMIN:
250d9320e22SCraig Topper   case TargetOpcode::G_PTR_ADD:
251cfdafc1eSCraig Topper   case TargetOpcode::G_PTRTOINT:
252cfdafc1eSCraig Topper   case TargetOpcode::G_INTTOPTR:
2530b8379bfSCraig Topper   case TargetOpcode::G_FADD:
2540b8379bfSCraig Topper   case TargetOpcode::G_FSUB:
2550b8379bfSCraig Topper   case TargetOpcode::G_FMUL:
2560b8379bfSCraig Topper   case TargetOpcode::G_FDIV:
2570b8379bfSCraig Topper   case TargetOpcode::G_FABS:
2580b8379bfSCraig Topper   case TargetOpcode::G_FNEG:
2590b8379bfSCraig Topper   case TargetOpcode::G_FSQRT:
2600b8379bfSCraig Topper   case TargetOpcode::G_FMAXNUM:
261f2f18459SNikita Popov   case TargetOpcode::G_FMINNUM: {
2620b8379bfSCraig Topper     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
263852eb20bSCraig Topper     TypeSize Size = Ty.getSizeInBits();
264852eb20bSCraig Topper 
265852eb20bSCraig Topper     const ValueMapping *Mapping;
266852eb20bSCraig Topper     if (Ty.isVector())
267852eb20bSCraig Topper       Mapping = getVRBValueMapping(Size.getKnownMinValue());
268852eb20bSCraig Topper     else if (isPreISelGenericFloatingPointOpcode(Opc))
269852eb20bSCraig Topper       Mapping = getFPValueMapping(Size.getFixedValue());
270852eb20bSCraig Topper     else
271852eb20bSCraig Topper       Mapping = GPRValueMapping;
272852eb20bSCraig Topper 
273852eb20bSCraig Topper #ifndef NDEBUG
274852eb20bSCraig Topper     // Make sure all the operands are using similar size and type.
275852eb20bSCraig Topper     for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
276852eb20bSCraig Topper       LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
277852eb20bSCraig Topper       assert(Ty.isVector() == OpTy.isVector() &&
278852eb20bSCraig Topper              "Operand has incompatible type");
279852eb20bSCraig Topper       // Don't check size for GPR.
280852eb20bSCraig Topper       if (OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc))
281852eb20bSCraig Topper         assert(Size == OpTy.getSizeInBits() && "Operand has incompatible size");
2820b8379bfSCraig Topper     }
283852eb20bSCraig Topper #endif // End NDEBUG
284852eb20bSCraig Topper 
285852eb20bSCraig Topper     return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
286852eb20bSCraig Topper   }
287852eb20bSCraig Topper   case TargetOpcode::G_SEXTLOAD:
288852eb20bSCraig Topper   case TargetOpcode::G_ZEXTLOAD:
289852eb20bSCraig Topper     return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping,
290852eb20bSCraig Topper                                  NumOperands);
2916976dac0SMichael Maitland   case TargetOpcode::G_IMPLICIT_DEF: {
2926976dac0SMichael Maitland     Register Dst = MI.getOperand(0).getReg();
293ea798a79SMichael Maitland     LLT DstTy = MRI.getType(Dst);
294a853d799SCraig Topper     unsigned DstMinSize = DstTy.getSizeInBits().getKnownMinValue();
2956976dac0SMichael Maitland     auto Mapping = GPRValueMapping;
2966976dac0SMichael Maitland     // FIXME: May need to do a better job determining when to use FPRB.
2976976dac0SMichael Maitland     // For example, the look through COPY case:
2986976dac0SMichael Maitland     // %0:_(s32) = G_IMPLICIT_DEF
2996976dac0SMichael Maitland     // %1:_(s32) = COPY %0
3006976dac0SMichael Maitland     // $f10_d = COPY %1(s32)
301ea798a79SMichael Maitland     if (DstTy.isVector())
302ea798a79SMichael Maitland       Mapping = getVRBValueMapping(DstMinSize);
303a853d799SCraig Topper     else if (anyUseOnlyUseFP(Dst, MRI, TRI))
304a853d799SCraig Topper       Mapping = getFPValueMapping(DstMinSize);
305ea798a79SMichael Maitland 
3066976dac0SMichael Maitland     return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping,
3076976dac0SMichael Maitland                                  NumOperands);
3086976dac0SMichael Maitland   }
3090b8379bfSCraig Topper   }
3100b8379bfSCraig Topper 
3110b8379bfSCraig Topper   SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands);
3120b8379bfSCraig Topper 
3130b8379bfSCraig Topper   switch (Opc) {
31405300222SCraig Topper   case TargetOpcode::G_LOAD: {
31505300222SCraig Topper     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3161c66ef91SJiahan Xie     TypeSize Size = Ty.getSizeInBits();
3171c66ef91SJiahan Xie 
3180b8379bfSCraig Topper     OpdsMapping[1] = GPRValueMapping;
3191c66ef91SJiahan Xie 
320a1ba4fb4SCraig Topper     if (Ty.isVector()) {
321a1ba4fb4SCraig Topper       OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
3221c66ef91SJiahan Xie       break;
323a1ba4fb4SCraig Topper     }
324a1ba4fb4SCraig Topper 
325a1ba4fb4SCraig Topper     OpdsMapping[0] = GPRValueMapping;
326a1ba4fb4SCraig Topper 
32705300222SCraig Topper     // Use FPR64 for s64 loads on rv32.
3281c66ef91SJiahan Xie     if (GPRSize == 32 && Size.getFixedValue() == 64) {
32905300222SCraig Topper       assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
330*de6d0d2dSLuke Quinn       OpdsMapping[0] = getFPValueMapping(Size);
33105300222SCraig Topper       break;
33205300222SCraig Topper     }
33305300222SCraig Topper 
33405300222SCraig Topper     // Check if that load feeds fp instructions.
33505300222SCraig Topper     // In that case, we want the default mapping to be on FPR
33605300222SCraig Topper     // instead of blind map every scalar to GPR.
337*de6d0d2dSLuke Quinn     if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) {
33805300222SCraig Topper       // If we have at least one direct use in a FP instruction,
33905300222SCraig Topper       // assume this was a floating point load in the IR. If it was
34005300222SCraig Topper       // not, we would have had a bitcast before reaching that
34105300222SCraig Topper       // instruction.
342*de6d0d2dSLuke Quinn       OpdsMapping[0] = getFPValueMapping(Size);
343*de6d0d2dSLuke Quinn       break;
344*de6d0d2dSLuke Quinn     }
34505300222SCraig Topper 
34605300222SCraig Topper     break;
34705300222SCraig Topper   }
34805300222SCraig Topper   case TargetOpcode::G_STORE: {
34905300222SCraig Topper     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3501c66ef91SJiahan Xie     TypeSize Size = Ty.getSizeInBits();
3511c66ef91SJiahan Xie 
3520b8379bfSCraig Topper     OpdsMapping[1] = GPRValueMapping;
3531c66ef91SJiahan Xie 
354a1ba4fb4SCraig Topper     if (Ty.isVector()) {
355a1ba4fb4SCraig Topper       OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
3561c66ef91SJiahan Xie       break;
357a1ba4fb4SCraig Topper     }
358a1ba4fb4SCraig Topper 
359a1ba4fb4SCraig Topper     OpdsMapping[0] = GPRValueMapping;
3601c66ef91SJiahan Xie 
36105300222SCraig Topper     // Use FPR64 for s64 stores on rv32.
3621c66ef91SJiahan Xie     if (GPRSize == 32 && Size.getFixedValue() == 64) {
36305300222SCraig Topper       assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
3640b8379bfSCraig Topper       OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
36505300222SCraig Topper       break;
36605300222SCraig Topper     }
36705300222SCraig Topper 
36805300222SCraig Topper     MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
3690b8379bfSCraig Topper     if (onlyDefinesFP(*DefMI, MRI, TRI))
3700b8379bfSCraig Topper       OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
37105300222SCraig Topper     break;
37205300222SCraig Topper   }
3735f31dbd1SCraig Topper   case TargetOpcode::G_SELECT: {
3745f31dbd1SCraig Topper     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3755f31dbd1SCraig Topper 
376973e9dbdSMichael Maitland     if (Ty.isVector()) {
377973e9dbdSMichael Maitland       auto &Sel = cast<GSelect>(MI);
378973e9dbdSMichael Maitland       LLT TestTy = MRI.getType(Sel.getCondReg());
379973e9dbdSMichael Maitland       assert(TestTy.isVector() && "Unexpected condition argument type");
380973e9dbdSMichael Maitland       OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] =
381973e9dbdSMichael Maitland           getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
382973e9dbdSMichael Maitland       OpdsMapping[1] =
383973e9dbdSMichael Maitland           getVRBValueMapping(TestTy.getSizeInBits().getKnownMinValue());
384973e9dbdSMichael Maitland       break;
385973e9dbdSMichael Maitland     }
386973e9dbdSMichael Maitland 
3875f31dbd1SCraig Topper     // Try to minimize the number of copies. If we have more floating point
3885f31dbd1SCraig Topper     // constrained values than not, then we'll put everything on FPR. Otherwise,
3895f31dbd1SCraig Topper     // everything has to be on GPR.
3905f31dbd1SCraig Topper     unsigned NumFP = 0;
3915f31dbd1SCraig Topper 
392d345cfb5SCraig Topper     // Use FPR64 for s64 select on rv32.
393d345cfb5SCraig Topper     if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
394d345cfb5SCraig Topper       NumFP = 3;
395d345cfb5SCraig Topper     } else {
3965f31dbd1SCraig Topper       // Check if the uses of the result always produce floating point values.
3975f31dbd1SCraig Topper       //
3985f31dbd1SCraig Topper       // For example:
3995f31dbd1SCraig Topper       //
4005f31dbd1SCraig Topper       // %z = G_SELECT %cond %x %y
4015f31dbd1SCraig Topper       // fpr = G_FOO %z ...
4025f31dbd1SCraig Topper       if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
4035f31dbd1SCraig Topper                  [&](const MachineInstr &UseMI) {
4045f31dbd1SCraig Topper                    return onlyUsesFP(UseMI, MRI, TRI);
4055f31dbd1SCraig Topper                  }))
4065f31dbd1SCraig Topper         ++NumFP;
4075f31dbd1SCraig Topper 
4085f31dbd1SCraig Topper       // Check if the defs of the source values always produce floating point
4095f31dbd1SCraig Topper       // values.
4105f31dbd1SCraig Topper       //
4115f31dbd1SCraig Topper       // For example:
4125f31dbd1SCraig Topper       //
4135f31dbd1SCraig Topper       // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
4145f31dbd1SCraig Topper       // %z = G_SELECT %cond %x %y
4155f31dbd1SCraig Topper       //
4165f31dbd1SCraig Topper       // Also check whether or not the sources have already been decided to be
4175f31dbd1SCraig Topper       // FPR. Keep track of this.
4185f31dbd1SCraig Topper       //
4195f31dbd1SCraig Topper       // This doesn't check the condition, since the condition is always an
4205f31dbd1SCraig Topper       // integer.
4215f31dbd1SCraig Topper       for (unsigned Idx = 2; Idx < 4; ++Idx) {
4225f31dbd1SCraig Topper         Register VReg = MI.getOperand(Idx).getReg();
4235f31dbd1SCraig Topper         MachineInstr *DefMI = MRI.getVRegDef(VReg);
4245f31dbd1SCraig Topper         if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank ||
4255f31dbd1SCraig Topper             onlyDefinesFP(*DefMI, MRI, TRI))
4265f31dbd1SCraig Topper           ++NumFP;
4275f31dbd1SCraig Topper       }
428d345cfb5SCraig Topper     }
4295f31dbd1SCraig Topper 
4305f31dbd1SCraig Topper     // Condition operand is always GPR.
4310b8379bfSCraig Topper     OpdsMapping[1] = GPRValueMapping;
4325f31dbd1SCraig Topper 
4335f31dbd1SCraig Topper     const ValueMapping *Mapping = GPRValueMapping;
4345f31dbd1SCraig Topper     if (NumFP >= 2)
4355f31dbd1SCraig Topper       Mapping = getFPValueMapping(Ty.getSizeInBits());
4365f31dbd1SCraig Topper 
4375f31dbd1SCraig Topper     OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping;
438d9320e22SCraig Topper     break;
4395f31dbd1SCraig Topper   }
440d3177d8bSCraig Topper   case RISCV::G_FCVT_W_RV64:
441d3177d8bSCraig Topper   case RISCV::G_FCVT_WU_RV64:
442374fb412SCraig Topper   case TargetOpcode::G_FPTOSI:
4437c3c8a12SMin-Yih Hsu   case TargetOpcode::G_FPTOUI:
4447c3c8a12SMin-Yih Hsu   case RISCV::G_FCLASS: {
445374fb412SCraig Topper     LLT Ty = MRI.getType(MI.getOperand(1).getReg());
4460b8379bfSCraig Topper     OpdsMapping[0] = GPRValueMapping;
4470b8379bfSCraig Topper     OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits());
448374fb412SCraig Topper     break;
449374fb412SCraig Topper   }
450a6c80c4fSCraig Topper   case TargetOpcode::G_SITOFP:
451a6c80c4fSCraig Topper   case TargetOpcode::G_UITOFP: {
452a6c80c4fSCraig Topper     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4530b8379bfSCraig Topper     OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
4540b8379bfSCraig Topper     OpdsMapping[1] = GPRValueMapping;
455a6c80c4fSCraig Topper     break;
456a6c80c4fSCraig Topper   }
457fdbff881SCraig Topper   case TargetOpcode::G_FCMP: {
458fdbff881SCraig Topper     LLT Ty = MRI.getType(MI.getOperand(2).getReg());
459fdbff881SCraig Topper 
460fdbff881SCraig Topper     unsigned Size = Ty.getSizeInBits();
461fdbff881SCraig Topper 
4620b8379bfSCraig Topper     OpdsMapping[0] = GPRValueMapping;
4630b8379bfSCraig Topper     OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size);
464fdbff881SCraig Topper     break;
465fdbff881SCraig Topper   }
466dbb9043dSMichael Maitland   case TargetOpcode::G_MERGE_VALUES: {
467dbb9043dSMichael Maitland     // Use FPR64 for s64 merge on rv32.
468dbb9043dSMichael Maitland     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
469dbb9043dSMichael Maitland     if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
470dbb9043dSMichael Maitland       assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
471dbb9043dSMichael Maitland       OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
472dbb9043dSMichael Maitland       OpdsMapping[1] = GPRValueMapping;
473dbb9043dSMichael Maitland       OpdsMapping[2] = GPRValueMapping;
474dbb9043dSMichael Maitland     }
475dbb9043dSMichael Maitland     break;
476dbb9043dSMichael Maitland   }
477dbb9043dSMichael Maitland   case TargetOpcode::G_UNMERGE_VALUES: {
478dbb9043dSMichael Maitland     // Use FPR64 for s64 unmerge on rv32.
479dbb9043dSMichael Maitland     LLT Ty = MRI.getType(MI.getOperand(2).getReg());
480dbb9043dSMichael Maitland     if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
481dbb9043dSMichael Maitland       assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
482dbb9043dSMichael Maitland       OpdsMapping[0] = GPRValueMapping;
483dbb9043dSMichael Maitland       OpdsMapping[1] = GPRValueMapping;
484dbb9043dSMichael Maitland       OpdsMapping[2] = getFPValueMapping(Ty.getSizeInBits());
485dbb9043dSMichael Maitland     }
486dbb9043dSMichael Maitland     break;
487dbb9043dSMichael Maitland   }
488ca5b81bdSMichael Maitland   case TargetOpcode::G_SPLAT_VECTOR: {
489ca5b81bdSMichael Maitland     OpdsMapping[0] = getVRBValueMapping(MRI.getType(MI.getOperand(0).getReg())
490ca5b81bdSMichael Maitland                                             .getSizeInBits()
491ca5b81bdSMichael Maitland                                             .getKnownMinValue());
492ca5b81bdSMichael Maitland 
493ca5b81bdSMichael Maitland     LLT ScalarTy = MRI.getType(MI.getOperand(1).getReg());
494ca5b81bdSMichael Maitland     MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
495ca5b81bdSMichael Maitland     if ((GPRSize == 32 && ScalarTy.getSizeInBits() == 64) ||
496ca5b81bdSMichael Maitland         onlyDefinesFP(*DefMI, MRI, TRI)) {
497ca5b81bdSMichael Maitland       assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
498ca5b81bdSMichael Maitland       OpdsMapping[1] = getFPValueMapping(ScalarTy.getSizeInBits());
499ca5b81bdSMichael Maitland     } else
500ca5b81bdSMichael Maitland       OpdsMapping[1] = GPRValueMapping;
501ca5b81bdSMichael Maitland     break;
502ca5b81bdSMichael Maitland   }
503d9320e22SCraig Topper   default:
5048630cf21SCraig Topper     // By default map all scalars to GPR.
5058630cf21SCraig Topper     for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
5068630cf21SCraig Topper        auto &MO = MI.getOperand(Idx);
507181e8065SCraig Topper        if (!MO.isReg() || !MO.getReg())
5088630cf21SCraig Topper          continue;
509181e8065SCraig Topper        LLT Ty = MRI.getType(MO.getReg());
510181e8065SCraig Topper        if (!Ty.isValid())
511181e8065SCraig Topper          continue;
512181e8065SCraig Topper 
51305f673bcSMichael Maitland        if (Ty.isVector())
51405f673bcSMichael Maitland          OpdsMapping[Idx] =
51505f673bcSMichael Maitland              getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
51605f673bcSMichael Maitland        else if (isPreISelGenericFloatingPointOpcode(Opc))
517181e8065SCraig Topper          OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());
518181e8065SCraig Topper        else
5198630cf21SCraig Topper          OpdsMapping[Idx] = GPRValueMapping;
5208630cf21SCraig Topper     }
5218630cf21SCraig Topper     break;
522d9320e22SCraig Topper   }
523d9320e22SCraig Topper 
5240b8379bfSCraig Topper   return getInstructionMapping(DefaultMappingID, /*Cost=*/1,
5250b8379bfSCraig Topper                                getOperandsMapping(OpdsMapping), NumOperands);
526d9320e22SCraig Topper }
527