brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 9f9ae2f Raw
562 lines · cpp
1//===-- RISCVRegisterBankInfo.cpp -------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements the targeting of the RegisterBankInfo class for RISC-V.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//12 13#include "RISCVRegisterBankInfo.h"14#include "MCTargetDesc/RISCVMCTargetDesc.h"15#include "RISCVSubtarget.h"16#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/RegisterBank.h"19#include "llvm/CodeGen/RegisterBankInfo.h"20#include "llvm/CodeGen/TargetRegisterInfo.h"21 22#define GET_TARGET_REGBANK_IMPL23#include "RISCVGenRegisterBank.inc"24 25namespace llvm {26namespace RISCV {27 28const RegisterBankInfo::PartialMapping PartMappings[] = {29    // clang-format off30    {0, 32, GPRBRegBank},31    {0, 64, GPRBRegBank},32    {0, 16, FPRBRegBank},33    {0, 32, FPRBRegBank},34    {0, 64, FPRBRegBank},35    {0, 64, VRBRegBank},36    {0, 128, VRBRegBank},37    {0, 256, VRBRegBank},38    {0, 512, VRBRegBank},39    // clang-format on40};41 42enum PartialMappingIdx {43  PMI_GPRB32 = 0,44  PMI_GPRB64 = 1,45  PMI_FPRB16 = 2,46  PMI_FPRB32 = 3,47  PMI_FPRB64 = 4,48  PMI_VRB64 = 5,49  PMI_VRB128 = 6,50  PMI_VRB256 = 7,51  PMI_VRB512 = 8,52};53 54const RegisterBankInfo::ValueMapping ValueMappings[] = {55    // Invalid value mapping.56    {nullptr, 0},57    // Maximum 3 GPR operands; 32 bit.58    {&PartMappings[PMI_GPRB32], 1},59    {&PartMappings[PMI_GPRB32], 1},60    {&PartMappings[PMI_GPRB32], 1},61    // Maximum 3 GPR operands; 64 bit.62    {&PartMappings[PMI_GPRB64], 1},63    {&PartMappings[PMI_GPRB64], 1},64    {&PartMappings[PMI_GPRB64], 1},65    // Maximum 3 FPR operands; 16 bit.66    {&PartMappings[PMI_FPRB16], 1},67    {&PartMappings[PMI_FPRB16], 1},68    {&PartMappings[PMI_FPRB16], 1},69    // Maximum 3 FPR operands; 32 bit.70    {&PartMappings[PMI_FPRB32], 1},71    {&PartMappings[PMI_FPRB32], 1},72    {&PartMappings[PMI_FPRB32], 1},73    // Maximum 3 FPR operands; 64 bit.74    {&PartMappings[PMI_FPRB64], 1},75    {&PartMappings[PMI_FPRB64], 1},76    {&PartMappings[PMI_FPRB64], 1},77    // Maximum 3 VR LMUL={1, MF2, MF4, MF8} operands.78    {&PartMappings[PMI_VRB64], 1},79    {&PartMappings[PMI_VRB64], 1},80    {&PartMappings[PMI_VRB64], 1},81    // Maximum 3 VR LMUL=2 operands.82    {&PartMappings[PMI_VRB128], 1},83    {&PartMappings[PMI_VRB128], 1},84    {&PartMappings[PMI_VRB128], 1},85    // Maximum 3 VR LMUL=4 operands.86    {&PartMappings[PMI_VRB256], 1},87    {&PartMappings[PMI_VRB256], 1},88    {&PartMappings[PMI_VRB256], 1},89    // Maximum 3 VR LMUL=8 operands.90    {&PartMappings[PMI_VRB512], 1},91    {&PartMappings[PMI_VRB512], 1},92    {&PartMappings[PMI_VRB512], 1},93};94 95enum ValueMappingIdx {96  InvalidIdx = 0,97  GPRB32Idx = 1,98  GPRB64Idx = 4,99  FPRB16Idx = 7,100  FPRB32Idx = 10,101  FPRB64Idx = 13,102  VRB64Idx = 16,103  VRB128Idx = 19,104  VRB256Idx = 22,105  VRB512Idx = 25,106};107} // namespace RISCV108} // namespace llvm109 110using namespace llvm;111 112RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode)113    : RISCVGenRegisterBankInfo(HwMode) {}114 115static const RegisterBankInfo::ValueMapping *getFPValueMapping(unsigned Size) {116  unsigned Idx;117  switch (Size) {118  default:119    llvm_unreachable("Unexpected size");120  case 16:121    Idx = RISCV::FPRB16Idx;122    break;123  case 32:124    Idx = RISCV::FPRB32Idx;125    break;126  case 64:127    Idx = RISCV::FPRB64Idx;128    break;129  }130  return &RISCV::ValueMappings[Idx];131}132 133// TODO: Make this more like AArch64?134bool RISCVRegisterBankInfo::hasFPConstraints(135    const MachineInstr &MI, const MachineRegisterInfo &MRI,136    const TargetRegisterInfo &TRI) const {137  if (isPreISelGenericFloatingPointOpcode(MI.getOpcode()))138    return true;139 140  // If we have a copy instruction, we could be feeding floating point141  // instructions.142  if (MI.getOpcode() != TargetOpcode::COPY)143    return false;144 145  return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) == &RISCV::FPRBRegBank;146}147 148bool RISCVRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,149                                       const MachineRegisterInfo &MRI,150                                       const TargetRegisterInfo &TRI) const {151  switch (MI.getOpcode()) {152  case RISCV::G_FCVT_W_RV64:153  case RISCV::G_FCVT_WU_RV64:154  case RISCV::G_FCLASS:155  case TargetOpcode::G_FPTOSI:156  case TargetOpcode::G_FPTOUI:157  case TargetOpcode::G_FCMP:158    return true;159  default:160    break;161  }162 163  return hasFPConstraints(MI, MRI, TRI);164}165 166bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,167                                          const MachineRegisterInfo &MRI,168                                          const TargetRegisterInfo &TRI) const {169  switch (MI.getOpcode()) {170  case TargetOpcode::G_SITOFP:171  case TargetOpcode::G_UITOFP:172    return true;173  default:174    break;175  }176 177  return hasFPConstraints(MI, MRI, TRI);178}179 180bool RISCVRegisterBankInfo::anyUseOnlyUseFP(181    Register Def, const MachineRegisterInfo &MRI,182    const TargetRegisterInfo &TRI) const {183  return any_of(184      MRI.use_nodbg_instructions(Def),185      [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); });186}187 188static const RegisterBankInfo::ValueMapping *getVRBValueMapping(unsigned Size) {189  unsigned Idx;190 191  if (Size <= 64)192    Idx = RISCV::VRB64Idx;193  else if (Size == 128)194    Idx = RISCV::VRB128Idx;195  else if (Size == 256)196    Idx = RISCV::VRB256Idx;197  else if (Size == 512)198    Idx = RISCV::VRB512Idx;199  else200    llvm::report_fatal_error("Invalid Size");201 202  return &RISCV::ValueMappings[Idx];203}204 205const RegisterBankInfo::InstructionMapping &206RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {207  const unsigned Opc = MI.getOpcode();208 209  // Try the default logic for non-generic instructions that are either copies210  // or already have some operands assigned to banks.211  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {212    const InstructionMapping &Mapping = getInstrMappingImpl(MI);213    if (Mapping.isValid())214      return Mapping;215  }216 217  const MachineFunction &MF = *MI.getParent()->getParent();218  const MachineRegisterInfo &MRI = MF.getRegInfo();219  const TargetSubtargetInfo &STI = MF.getSubtarget();220  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();221 222  unsigned GPRSize = getMaximumSize(RISCV::GPRBRegBankID);223  assert((GPRSize == 32 || GPRSize == 64) && "Unexpected GPR size");224 225  unsigned NumOperands = MI.getNumOperands();226  const ValueMapping *GPRValueMapping =227      &RISCV::ValueMappings[GPRSize == 64 ? RISCV::GPRB64Idx228                                          : RISCV::GPRB32Idx];229 230  switch (Opc) {231  case TargetOpcode::G_ADD:232  case TargetOpcode::G_SUB:233  case TargetOpcode::G_SHL:234  case TargetOpcode::G_ASHR:235  case TargetOpcode::G_LSHR:236  case TargetOpcode::G_AND:237  case TargetOpcode::G_OR:238  case TargetOpcode::G_XOR:239  case TargetOpcode::G_MUL:240  case TargetOpcode::G_SDIV:241  case TargetOpcode::G_SREM:242  case TargetOpcode::G_SMULH:243  case TargetOpcode::G_SMAX:244  case TargetOpcode::G_SMIN:245  case TargetOpcode::G_UDIV:246  case TargetOpcode::G_UREM:247  case TargetOpcode::G_UMULH:248  case TargetOpcode::G_UMAX:249  case TargetOpcode::G_UMIN:250  case TargetOpcode::G_PTR_ADD:251  case TargetOpcode::G_PTRTOINT:252  case TargetOpcode::G_INTTOPTR:253  case TargetOpcode::G_FADD:254  case TargetOpcode::G_FSUB:255  case TargetOpcode::G_FMUL:256  case TargetOpcode::G_FDIV:257  case TargetOpcode::G_FABS:258  case TargetOpcode::G_FNEG:259  case TargetOpcode::G_FSQRT:260  case TargetOpcode::G_FMAXNUM:261  case TargetOpcode::G_FMINNUM: {262    LLT Ty = MRI.getType(MI.getOperand(0).getReg());263    TypeSize Size = Ty.getSizeInBits();264 265    const ValueMapping *Mapping;266    if (Ty.isVector())267      Mapping = getVRBValueMapping(Size.getKnownMinValue());268    else if (isPreISelGenericFloatingPointOpcode(Opc))269      Mapping = getFPValueMapping(Size.getFixedValue());270    else271      Mapping = GPRValueMapping;272 273#ifndef NDEBUG274    // Make sure all the operands are using similar size and type.275    for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {276      LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());277      assert(Ty.isVector() == OpTy.isVector() &&278             "Operand has incompatible type");279      // Don't check size for GPR.280      if (OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc))281        assert(Size == OpTy.getSizeInBits() && "Operand has incompatible size");282    }283#endif // End NDEBUG284 285    return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);286  }287  case TargetOpcode::G_SEXTLOAD:288  case TargetOpcode::G_ZEXTLOAD:289    return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping,290                                 NumOperands);291  case TargetOpcode::G_IMPLICIT_DEF: {292    Register Dst = MI.getOperand(0).getReg();293    LLT DstTy = MRI.getType(Dst);294    unsigned DstMinSize = DstTy.getSizeInBits().getKnownMinValue();295    auto Mapping = GPRValueMapping;296    // FIXME: May need to do a better job determining when to use FPRB.297    // For example, the look through COPY case:298    // %0:_(s32) = G_IMPLICIT_DEF299    // %1:_(s32) = COPY %0300    // $f10_d = COPY %1(s32)301    if (DstTy.isVector())302      Mapping = getVRBValueMapping(DstMinSize);303    else if (anyUseOnlyUseFP(Dst, MRI, TRI))304      Mapping = getFPValueMapping(DstMinSize);305 306    return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping,307                                 NumOperands);308  }309  }310 311  SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands);312 313  switch (Opc) {314  case TargetOpcode::G_LOAD: {315    LLT Ty = MRI.getType(MI.getOperand(0).getReg());316    TypeSize Size = Ty.getSizeInBits();317 318    OpdsMapping[1] = GPRValueMapping;319 320    if (Ty.isVector()) {321      OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());322      break;323    }324 325    OpdsMapping[0] = GPRValueMapping;326 327    // Atomics always use GPR destinations. Don't refine any further.328    if (cast<GLoad>(MI).isAtomic())329      break;330 331    // Use FPR64 for s64 loads on rv32.332    if (GPRSize == 32 && Size.getFixedValue() == 64) {333      assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());334      OpdsMapping[0] = getFPValueMapping(Size);335      break;336    }337 338    // Check if that load feeds fp instructions.339    // In that case, we want the default mapping to be on FPR340    // instead of blind map every scalar to GPR.341    if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) {342      // If we have at least one direct use in a FP instruction,343      // assume this was a floating point load in the IR. If it was344      // not, we would have had a bitcast before reaching that345      // instruction.346      OpdsMapping[0] = getFPValueMapping(Size);347      break;348    }349 350    break;351  }352  case TargetOpcode::G_STORE: {353    LLT Ty = MRI.getType(MI.getOperand(0).getReg());354    TypeSize Size = Ty.getSizeInBits();355 356    OpdsMapping[1] = GPRValueMapping;357 358    if (Ty.isVector()) {359      OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());360      break;361    }362 363    OpdsMapping[0] = GPRValueMapping;364 365    // Atomics always use GPR sources. Don't refine any further.366    if (cast<GStore>(MI).isAtomic())367      break;368 369    // Use FPR64 for s64 stores on rv32.370    if (GPRSize == 32 && Size.getFixedValue() == 64) {371      assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());372      OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());373      break;374    }375 376    MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());377    if (onlyDefinesFP(*DefMI, MRI, TRI))378      OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());379    break;380  }381  case TargetOpcode::G_SELECT: {382    LLT Ty = MRI.getType(MI.getOperand(0).getReg());383 384    if (Ty.isVector()) {385      auto &Sel = cast<GSelect>(MI);386      LLT TestTy = MRI.getType(Sel.getCondReg());387      assert(TestTy.isVector() && "Unexpected condition argument type");388      OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] =389          getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());390      OpdsMapping[1] =391          getVRBValueMapping(TestTy.getSizeInBits().getKnownMinValue());392      break;393    }394 395    // Try to minimize the number of copies. If we have more floating point396    // constrained values than not, then we'll put everything on FPR. Otherwise,397    // everything has to be on GPR.398    unsigned NumFP = 0;399 400    // Use FPR64 for s64 select on rv32.401    if (GPRSize == 32 && Ty.getSizeInBits() == 64) {402      NumFP = 3;403    } else {404      // Check if the uses of the result always produce floating point values.405      //406      // For example:407      //408      // %z = G_SELECT %cond %x %y409      // fpr = G_FOO %z ...410      if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),411                 [&](const MachineInstr &UseMI) {412                   return onlyUsesFP(UseMI, MRI, TRI);413                 }))414        ++NumFP;415 416      // Check if the defs of the source values always produce floating point417      // values.418      //419      // For example:420      //421      // %x = G_SOMETHING_ALWAYS_FLOAT %a ...422      // %z = G_SELECT %cond %x %y423      //424      // Also check whether or not the sources have already been decided to be425      // FPR. Keep track of this.426      //427      // This doesn't check the condition, since the condition is always an428      // integer.429      for (unsigned Idx = 2; Idx < 4; ++Idx) {430        Register VReg = MI.getOperand(Idx).getReg();431        MachineInstr *DefMI = MRI.getVRegDef(VReg);432        if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank ||433            onlyDefinesFP(*DefMI, MRI, TRI))434          ++NumFP;435      }436    }437 438    // Condition operand is always GPR.439    OpdsMapping[1] = GPRValueMapping;440 441    const ValueMapping *Mapping = GPRValueMapping;442    if (NumFP >= 2)443      Mapping = getFPValueMapping(Ty.getSizeInBits());444 445    OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping;446    break;447  }448  case RISCV::G_FCVT_W_RV64:449  case RISCV::G_FCVT_WU_RV64:450  case TargetOpcode::G_FPTOSI:451  case TargetOpcode::G_FPTOUI:452  case RISCV::G_FCLASS: {453    LLT Ty = MRI.getType(MI.getOperand(1).getReg());454    OpdsMapping[0] = GPRValueMapping;455    OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits());456    break;457  }458  case TargetOpcode::G_SITOFP:459  case TargetOpcode::G_UITOFP: {460    LLT Ty = MRI.getType(MI.getOperand(0).getReg());461    OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());462    OpdsMapping[1] = GPRValueMapping;463    break;464  }465  case TargetOpcode::G_FCMP: {466    LLT Ty = MRI.getType(MI.getOperand(2).getReg());467 468    unsigned Size = Ty.getSizeInBits();469 470    OpdsMapping[0] = GPRValueMapping;471    OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size);472    break;473  }474  case TargetOpcode::G_MERGE_VALUES: {475    // Use FPR64 for s64 merge on rv32.476    LLT Ty = MRI.getType(MI.getOperand(0).getReg());477    if (GPRSize == 32 && Ty.getSizeInBits() == 64) {478      assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());479      OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());480      OpdsMapping[1] = GPRValueMapping;481      OpdsMapping[2] = GPRValueMapping;482    }483    break;484  }485  case TargetOpcode::G_UNMERGE_VALUES: {486    // Use FPR64 for s64 unmerge on rv32.487    LLT Ty = MRI.getType(MI.getOperand(2).getReg());488    if (GPRSize == 32 && Ty.getSizeInBits() == 64) {489      assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());490      OpdsMapping[0] = GPRValueMapping;491      OpdsMapping[1] = GPRValueMapping;492      OpdsMapping[2] = getFPValueMapping(Ty.getSizeInBits());493    }494    break;495  }496  case TargetOpcode::G_SPLAT_VECTOR: {497    OpdsMapping[0] = getVRBValueMapping(MRI.getType(MI.getOperand(0).getReg())498                                            .getSizeInBits()499                                            .getKnownMinValue());500 501    LLT ScalarTy = MRI.getType(MI.getOperand(1).getReg());502    MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());503    if ((GPRSize == 32 && ScalarTy.getSizeInBits() == 64) ||504        onlyDefinesFP(*DefMI, MRI, TRI)) {505      assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());506      OpdsMapping[1] = getFPValueMapping(ScalarTy.getSizeInBits());507    } else508      OpdsMapping[1] = GPRValueMapping;509    break;510  }511  case TargetOpcode::G_INTRINSIC: {512    Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();513 514    if (const RISCVVIntrinsicsTable::RISCVVIntrinsicInfo *II =515            RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntrinsicID)) {516      unsigned ScalarIdx = -1;517      if (II->hasScalarOperand()) {518        ScalarIdx = II->ScalarOperand + 2;519      }520      for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {521        const MachineOperand &MO = MI.getOperand(Idx);522        if (!MO.isReg())523          continue;524        LLT Ty = MRI.getType(MO.getReg());525        if (Ty.isVector()) {526          OpdsMapping[Idx] =527              getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());528        } else if (II->IsFPIntrinsic && ScalarIdx == Idx) {529          // Chose the right FPR for scalar operand of RVV intrinsics.530          OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());531        } else {532          OpdsMapping[Idx] = GPRValueMapping;533        }534      }535    }536    break;537  }538  default:539    // By default map all scalars to GPR.540    for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {541       auto &MO = MI.getOperand(Idx);542       if (!MO.isReg() || !MO.getReg())543         continue;544       LLT Ty = MRI.getType(MO.getReg());545       if (!Ty.isValid())546         continue;547 548       if (Ty.isVector())549         OpdsMapping[Idx] =550             getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());551       else if (isPreISelGenericFloatingPointOpcode(Opc))552         OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());553       else554         OpdsMapping[Idx] = GPRValueMapping;555    }556    break;557  }558 559  return getInstructionMapping(DefaultMappingID, /*Cost=*/1,560                               getOperandsMapping(OpdsMapping), NumOperands);561}562