diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -734,6 +734,10 @@ bool shouldNormalizeToSelectSequence(LLVMContext &, EVT) const override { return false; }; + + /// For available scheduling models FDIV + two independent FMULs are much + /// faster than two FDIVs. + unsigned combineRepeatedFPDivisors() const override; }; namespace RISCVVIntrinsicsTable { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -59,6 +59,12 @@ "VWADD_W) with splat constants"), cl::init(false)); +static cl::opt NumRepeatedDivisors( + DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, + cl::desc("Set the minimum number of repetitions of a divisor to allow " + "transformation to multiplications by the reciprocal"), + cl::init(2)); + RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI) : TargetLowering(TM), Subtarget(STI) { @@ -1726,6 +1732,10 @@ return false; } +unsigned RISCVTargetLowering::combineRepeatedFPDivisors() const { + return NumRepeatedDivisors; +} + static SDValue getVLOperand(SDValue Op) { assert((Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || Op.getOpcode() == ISD::INTRINSIC_W_CHAIN) && diff --git a/llvm/test/CodeGen/RISCV/repeated-fp-divisors.ll b/llvm/test/CodeGen/RISCV/repeated-fp-divisors.ll --- a/llvm/test/CodeGen/RISCV/repeated-fp-divisors.ll +++ b/llvm/test/CodeGen/RISCV/repeated-fp-divisors.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s | FileCheck %s +; Negative test define void @single_fdiv(double %a0, double %a1, ptr %res) { ; CHECK-LABEL: single_fdiv: ; CHECK: # %bb.0: # %entry @@ -16,10 +17,13 @@ define void @two_fdivs(double %a0, double %a1, double %a2, ptr %res) { ; CHECK-LABEL: two_fdivs: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: fdiv.d ft0, fa1, fa0 -; CHECK-NEXT: fdiv.d ft1, fa2, fa0 -; CHECK-NEXT: fsd ft0, 0(a0) -; CHECK-NEXT: fsd ft1, 8(a0) +; CHECK-NEXT: lui a1, %hi(.LCPI1_0) +; CHECK-NEXT: fld ft0, %lo(.LCPI1_0)(a1) +; CHECK-NEXT: fdiv.d ft0, ft0, fa0 +; CHECK-NEXT: fmul.d ft1, fa1, ft0 +; CHECK-NEXT: fmul.d ft0, fa2, ft0 +; CHECK-NEXT: fsd ft1, 0(a0) +; CHECK-NEXT: fsd ft0, 8(a0) ; CHECK-NEXT: ret entry: %div = fdiv arcp double %a1, %a0 @@ -30,6 +34,7 @@ ret void } +; Negative test define void @no_arcp(double %a0, double %a1, double %a2, ptr %res) { ; CHECK-LABEL: no_arcp: ; CHECK: # %bb.0: # %entry