diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -842,6 +842,14 @@ } case ISD::ConstantFP: { const APFloat &APF = cast(Node)->getValueAPF(); + if (Subtarget->hasStdExtZfa()) { + if ((VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(APF) != -1) || + (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(APF) != -1) || + (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(APF) != -1 && + !APF.isPosZero())) + break; + } + bool NegZeroF64 = APF.isNegZero() && VT == MVT::f64; SDValue Imm; // For +0.0 or f64 -0.0 we need to start from X0. For all others, we will 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 @@ -1518,6 +1518,14 @@ bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const { + if (Subtarget.hasStdExtZfa()) { + if ((VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(Imm) != -1) || + (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(Imm) != -1) || + (VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(Imm) != -1 && + !Imm.isPosZero())) + return true; + } + if (VT == MVT::f16 && !Subtarget.hasStdExtZfhOrZfhmin()) return false; if (VT == MVT::f32 && !Subtarget.hasStdExtF()) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td @@ -178,7 +178,21 @@ // Codegen patterns //===----------------------------------------------------------------------===// +def fp32imm_to_loadfpimm : SDNodeXFormgetTargetConstant(RISCVLoadFPImm::getLoadFP32Imm(N->getValueAPF()), + SDLoc(N), Subtarget->getXLenVT());}]>; + +def fp64imm_to_loadfpimm : SDNodeXFormgetTargetConstant(RISCVLoadFPImm::getLoadFP64Imm(N->getValueAPF()), + SDLoc(N), Subtarget->getXLenVT());}]>; + +def fp16imm_to_loadfpimm : SDNodeXFormgetTargetConstant(RISCVLoadFPImm::getLoadFP16Imm(N->getValueAPF()), + SDLoc(N), Subtarget->getXLenVT());}]>; + let Predicates = [HasStdExtZfa] in { +def : Pat<(f32 fpimm:$imm), (FLI_S (fp32imm_to_loadfpimm fpimm:$imm))>; + def: PatFprFpr; def: PatFprFpr; @@ -201,6 +215,8 @@ } // Predicates = [HasStdExtZfa] let Predicates = [HasStdExtZfa, HasStdExtD] in { +def : Pat<(f64 fpimm:$imm), (FLI_D (fp64imm_to_loadfpimm fpimm:$imm))>; + def: PatFprFpr; def: PatFprFpr; @@ -229,6 +245,8 @@ } let Predicates = [HasStdExtZfa, HasStdExtZfh] in { +def : Pat<(f16 fpimm:$imm), (FLI_H (fp16imm_to_loadfpimm fpimm:$imm))>; + def: PatFprFpr; def: PatFprFpr; diff --git a/llvm/test/CodeGen/RISCV/double-zfa.ll b/llvm/test/CodeGen/RISCV/double-zfa.ll --- a/llvm/test/CodeGen/RISCV/double-zfa.ll +++ b/llvm/test/CodeGen/RISCV/double-zfa.ll @@ -4,6 +4,79 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+experimental-zfa,+d < %s \ ; RUN: | FileCheck --check-prefixes=CHECK,RV64DZFA %s +define double @loadfpimm1() { +; CHECK-LABEL: loadfpimm1: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, 6.250000e-02 +; CHECK-NEXT: ret + ret double 0.0625 +} + +define double @loadfpimm2() { +; CHECK-LABEL: loadfpimm2: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, 7.500000e-01 +; CHECK-NEXT: ret + ret double 0.75 +} + +define double @loadfpimm3() { +; CHECK-LABEL: loadfpimm3: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, 1.250000e+00 +; CHECK-NEXT: ret + ret double 1.25 +} + +define double @loadfpimm4() { +; CHECK-LABEL: loadfpimm4: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, 3.000000e+00 +; CHECK-NEXT: ret + ret double 3.0 +} + +define double @loadfpimm5() { +; CHECK-LABEL: loadfpimm5: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, 2.560000e+02 +; CHECK-NEXT: ret + ret double 256.0 +} + +define double @loadfpimm6() { +; CHECK-LABEL: loadfpimm6: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, inf +; CHECK-NEXT: ret + ret double 0x7FF0000000000000 +} + +define double @loadfpimm7() { +; CHECK-LABEL: loadfpimm7: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, nan +; CHECK-NEXT: ret + ret double 0x7FF8000000000000 +} + +define double @loadfpimm8() { +; CHECK-LABEL: loadfpimm8: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.d fa0, min +; CHECK-NEXT: ret + ret double 0x0010000000000000 +} + +define double @loadfpimm9() { +; CHECK-LABEL: loadfpimm9: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI8_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI8_0)(a0) +; CHECK-NEXT: ret + ret double 255.0 +} + declare double @llvm.minimum.f64(double, double) define double @fminm_d(double %a, double %b) nounwind { diff --git a/llvm/test/CodeGen/RISCV/float-zfa.ll b/llvm/test/CodeGen/RISCV/float-zfa.ll --- a/llvm/test/CodeGen/RISCV/float-zfa.ll +++ b/llvm/test/CodeGen/RISCV/float-zfa.ll @@ -4,6 +4,79 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa < %s \ ; RUN: | FileCheck %s +define float @loadfpimm1() { +; CHECK-LABEL: loadfpimm1: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, 6.250000e-02 +; CHECK-NEXT: ret + ret float 0.0625 +} + +define float @loadfpimm2() { +; CHECK-LABEL: loadfpimm2: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, 7.500000e-01 +; CHECK-NEXT: ret + ret float 0.75 +} + +define float @loadfpimm3() { +; CHECK-LABEL: loadfpimm3: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, 1.250000e+00 +; CHECK-NEXT: ret + ret float 1.25 +} + +define float @loadfpimm4() { +; CHECK-LABEL: loadfpimm4: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, 3.000000e+00 +; CHECK-NEXT: ret + ret float 3.0 +} + +define float @loadfpimm5() { +; CHECK-LABEL: loadfpimm5: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, 2.560000e+02 +; CHECK-NEXT: ret + ret float 256.0 +} + +define float @loadfpimm6() { +; CHECK-LABEL: loadfpimm6: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, inf +; CHECK-NEXT: ret + ret float 0x7FF0000000000000 +} + +define float @loadfpimm7() { +; CHECK-LABEL: loadfpimm7: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, nan +; CHECK-NEXT: ret + ret float 0x7FF8000000000000 +} + +define float @loadfpimm8() { +; CHECK-LABEL: loadfpimm8: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.s fa0, min +; CHECK-NEXT: ret + ret float 0x3810000000000000 +} + +define float @loadfpimm9() { +; CHECK-LABEL: loadfpimm9: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, 276464 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret + ret float 255.0 +} + declare float @llvm.minimum.f32(float, float) define float @fminm_s(float %a, float %b) nounwind { diff --git a/llvm/test/CodeGen/RISCV/half-zfa.ll b/llvm/test/CodeGen/RISCV/half-zfa.ll --- a/llvm/test/CodeGen/RISCV/half-zfa.ll +++ b/llvm/test/CodeGen/RISCV/half-zfa.ll @@ -4,6 +4,79 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa,+zfh < %s \ ; RUN: | FileCheck %s +define half @loadfpimm1() { +; CHECK-LABEL: loadfpimm1: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, 6.250000e-02 +; CHECK-NEXT: ret + ret half 0.0625 +} + +define half @loadfpimm2() { +; CHECK-LABEL: loadfpimm2: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, 7.500000e-01 +; CHECK-NEXT: ret + ret half 0.75 +} + +define half @loadfpimm3() { +; CHECK-LABEL: loadfpimm3: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, 1.250000e+00 +; CHECK-NEXT: ret + ret half 1.25 +} + +define half @loadfpimm4() { +; CHECK-LABEL: loadfpimm4: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, 3.000000e+00 +; CHECK-NEXT: ret + ret half 3.0 +} + +define half @loadfpimm5() { +; CHECK-LABEL: loadfpimm5: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, 2.560000e+02 +; CHECK-NEXT: ret + ret half 256.0 +} + +define half @loadfpimm6() { +; CHECK-LABEL: loadfpimm6: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, inf +; CHECK-NEXT: ret + ret half 0xH7C00 +} + +define half @loadfpimm7() { +; CHECK-LABEL: loadfpimm7: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, nan +; CHECK-NEXT: ret + ret half 0xH7E00 +} + +define half @loadfpimm8() { +; CHECK-LABEL: loadfpimm8: +; CHECK: # %bb.0: +; CHECK-NEXT: fli.h fa0, min +; CHECK-NEXT: ret + ret half 0xH0400 +} + +define half @loadfpimm9() { +; CHECK-LABEL: loadfpimm9: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a0, %hi(.LCPI8_0) +; CHECK-NEXT: flh fa0, %lo(.LCPI8_0)(a0) +; CHECK-NEXT: ret + ret half 255.0 +} + declare half @llvm.minimum.f16(half, half) define half @fminm_h(half %a, half %b) nounwind {