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