Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -704,6 +704,13 @@ } case ISD::ConstantFP: { const APFloat &APF = cast(Node)->getValueAPF(); + if (Subtarget->hasStdExtZfa()) { + if ((VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(APF) != -1) || + (VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(APF) != -1) || + (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(APF) != -1)) + 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 Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1485,6 +1485,13 @@ bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const { + if (Subtarget.hasStdExtZfa()) { + if ((VT == MVT::f32 && RISCVLoadFPImm::getLoadFP32Imm(Imm) != -1) || + (VT == MVT::f64 && RISCVLoadFPImm::getLoadFP64Imm(Imm) != -1) || + (VT == MVT::f16 && RISCVLoadFPImm::getLoadFP16Imm(Imm) != -1)) + return true; + } + if (VT == MVT::f16 && !Subtarget.hasStdExtZfhOrZfhmin()) return false; if (VT == MVT::f32 && !Subtarget.hasStdExtF()) Index: llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td @@ -157,7 +157,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; @@ -180,6 +194,8 @@ } // Predicates = [HasStdExtZfa] let Predicates = [HasStdExtZfa, HasStdExtD] in { +def : Pat<(f64 fpimm:$imm), (FLI_D (fp64imm_to_loadfpimm fpimm:$imm))>; + def: PatFprFpr; def: PatFprFpr; @@ -203,6 +219,8 @@ } // Predicates = [HasStdExtZfa, HasStdExtD] let Predicates = [HasStdExtZfa, HasStdExtZfh] in { +def : Pat<(f16 fpimm:$imm), (FLI_H (fp16imm_to_loadfpimm fpimm:$imm))>; + def: PatFprFpr; def: PatFprFpr; Index: llvm/test/CodeGen/RISCV/double-zfa.ll =================================================================== --- llvm/test/CodeGen/RISCV/double-zfa.ll +++ llvm/test/CodeGen/RISCV/double-zfa.ll @@ -4,6 +4,125 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+experimental-zfa,+d < %s \ ; RUN: | FileCheck --check-prefix=RV64DZFA %s +define double @loadfpimm1() { +; RV32IDZFA-LABEL: loadfpimm1: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, 6.250000e-02 +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm1: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, 6.250000e-02 +; RV64DZFA-NEXT: ret + ret double 0.0625 +} + +define double @loadfpimm2() { +; RV32IDZFA-LABEL: loadfpimm2: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, 7.500000e-01 +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm2: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, 7.500000e-01 +; RV64DZFA-NEXT: ret + ret double 0.75 +} + +define double @loadfpimm3() { +; RV32IDZFA-LABEL: loadfpimm3: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, 1.250000e+00 +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm3: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, 1.250000e+00 +; RV64DZFA-NEXT: ret + ret double 1.25 +} + +define double @loadfpimm4() { +; RV32IDZFA-LABEL: loadfpimm4: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, 3.000000e+00 +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm4: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, 3.000000e+00 +; RV64DZFA-NEXT: ret + ret double 3.0 +} + +define double @loadfpimm5() { +; RV32IDZFA-LABEL: loadfpimm5: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, 2.560000e+02 +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm5: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, 2.560000e+02 +; RV64DZFA-NEXT: ret + ret double 256.0 +} + +define double @loadfpimm6() { +; RV32IDZFA-LABEL: loadfpimm6: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, inf +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm6: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, inf +; RV64DZFA-NEXT: ret + ret double 0x7FF0000000000000 +} + +define double @loadfpimm7() { +; RV32IDZFA-LABEL: loadfpimm7: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, nan +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm7: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, nan +; RV64DZFA-NEXT: ret + ret double 0x7FF8000000000000 +} + +define double @loadfpimm8() { +; RV32IDZFA-LABEL: loadfpimm8: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: fli.d fa0, min +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm8: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: fli.d fa0, min +; RV64DZFA-NEXT: ret + ret double 0x0010000000000000 +} + +define double @loadfpimm9() { +; RV32IDZFA-LABEL: loadfpimm9: +; RV32IDZFA: # %bb.0: +; RV32IDZFA-NEXT: lui a0, %hi(.LCPI8_0) +; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI8_0)(a0) +; RV32IDZFA-NEXT: ret +; +; RV64DZFA-LABEL: loadfpimm9: +; RV64DZFA: # %bb.0: +; RV64DZFA-NEXT: lui a0, %hi(.LCPI8_0) +; RV64DZFA-NEXT: fld fa0, %lo(.LCPI8_0)(a0) +; RV64DZFA-NEXT: ret + ret double 255.0 +} + declare double @llvm.minimum.f64(double, double) define double @fminm_d(double %a, double %b) nounwind { Index: llvm/test/CodeGen/RISCV/float-zfa.ll =================================================================== --- llvm/test/CodeGen/RISCV/float-zfa.ll +++ llvm/test/CodeGen/RISCV/float-zfa.ll @@ -4,6 +4,125 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa < %s \ ; RUN: | FileCheck --check-prefix=RV64IZFA %s +define float @loadfpimm1() { +; RV32IZFA-LABEL: loadfpimm1: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, 6.250000e-02 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm1: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, 6.250000e-02 +; RV64IZFA-NEXT: ret + ret float 0.0625 +} + +define float @loadfpimm2() { +; RV32IZFA-LABEL: loadfpimm2: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, 7.500000e-01 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm2: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, 7.500000e-01 +; RV64IZFA-NEXT: ret + ret float 0.75 +} + +define float @loadfpimm3() { +; RV32IZFA-LABEL: loadfpimm3: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, 1.250000e+00 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm3: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, 1.250000e+00 +; RV64IZFA-NEXT: ret + ret float 1.25 +} + +define float @loadfpimm4() { +; RV32IZFA-LABEL: loadfpimm4: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, 3.000000e+00 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm4: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, 3.000000e+00 +; RV64IZFA-NEXT: ret + ret float 3.0 +} + +define float @loadfpimm5() { +; RV32IZFA-LABEL: loadfpimm5: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, 2.560000e+02 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm5: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, 2.560000e+02 +; RV64IZFA-NEXT: ret + ret float 256.0 +} + +define float @loadfpimm6() { +; RV32IZFA-LABEL: loadfpimm6: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, inf +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm6: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, inf +; RV64IZFA-NEXT: ret + ret float 0x7FF0000000000000 +} + +define float @loadfpimm7() { +; RV32IZFA-LABEL: loadfpimm7: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, nan +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm7: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, nan +; RV64IZFA-NEXT: ret + ret float 0x7FF8000000000000 +} + +define float @loadfpimm8() { +; RV32IZFA-LABEL: loadfpimm8: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: fli.s fa0, min +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm8: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: fli.s fa0, min +; RV64IZFA-NEXT: ret + ret float 0x3810000000000000 +} + +define float @loadfpimm9() { +; RV32IZFA-LABEL: loadfpimm9: +; RV32IZFA: # %bb.0: +; RV32IZFA-NEXT: lui a0, 276464 +; RV32IZFA-NEXT: fmv.w.x fa0, a0 +; RV32IZFA-NEXT: ret +; +; RV64IZFA-LABEL: loadfpimm9: +; RV64IZFA: # %bb.0: +; RV64IZFA-NEXT: lui a0, 276464 +; RV64IZFA-NEXT: fmv.w.x fa0, a0 +; RV64IZFA-NEXT: ret + ret float 255.0 +} + declare float @llvm.minimum.f32(float, float) define float @fminm_s(float %a, float %b) nounwind { Index: llvm/test/CodeGen/RISCV/half-zfa.ll =================================================================== --- llvm/test/CodeGen/RISCV/half-zfa.ll +++ llvm/test/CodeGen/RISCV/half-zfa.ll @@ -4,6 +4,125 @@ ; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+experimental-zfa,+zfh < %s \ ; RUN: | FileCheck --check-prefix=RV64HZFA %s +define half @loadfpimm1() { +; RV32IHZFA-LABEL: loadfpimm1: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, 6.250000e-02 +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm1: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, 6.250000e-02 +; RV64HZFA-NEXT: ret + ret half 0.0625 +} + +define half @loadfpimm2() { +; RV32IHZFA-LABEL: loadfpimm2: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, 7.500000e-01 +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm2: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, 7.500000e-01 +; RV64HZFA-NEXT: ret + ret half 0.75 +} + +define half @loadfpimm3() { +; RV32IHZFA-LABEL: loadfpimm3: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, 1.250000e+00 +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm3: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, 1.250000e+00 +; RV64HZFA-NEXT: ret + ret half 1.25 +} + +define half @loadfpimm4() { +; RV32IHZFA-LABEL: loadfpimm4: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, 3.000000e+00 +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm4: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, 3.000000e+00 +; RV64HZFA-NEXT: ret + ret half 3.0 +} + +define half @loadfpimm5() { +; RV32IHZFA-LABEL: loadfpimm5: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, 2.560000e+02 +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm5: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, 2.560000e+02 +; RV64HZFA-NEXT: ret + ret half 256.0 +} + +define half @loadfpimm6() { +; RV32IHZFA-LABEL: loadfpimm6: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, inf +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm6: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, inf +; RV64HZFA-NEXT: ret + ret half 0xH7C00 +} + +define half @loadfpimm7() { +; RV32IHZFA-LABEL: loadfpimm7: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, nan +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm7: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, nan +; RV64HZFA-NEXT: ret + ret half 0xH7E00 +} + +define half @loadfpimm8() { +; RV32IHZFA-LABEL: loadfpimm8: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: fli.h fa0, min +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm8: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: fli.h fa0, min +; RV64HZFA-NEXT: ret + ret half 0xH0400 +} + +define half @loadfpimm9() { +; RV32IHZFA-LABEL: loadfpimm9: +; RV32IHZFA: # %bb.0: +; RV32IHZFA-NEXT: lui a0, %hi(.LCPI8_0) +; RV32IHZFA-NEXT: flh fa0, %lo(.LCPI8_0)(a0) +; RV32IHZFA-NEXT: ret +; +; RV64HZFA-LABEL: loadfpimm9: +; RV64HZFA: # %bb.0: +; RV64HZFA-NEXT: lui a0, %hi(.LCPI8_0) +; RV64HZFA-NEXT: flh fa0, %lo(.LCPI8_0)(a0) +; RV64HZFA-NEXT: ret + ret half 255.0 +} + declare half @llvm.minimum.f16(half, half) define half @fminm_h(half %a, half %b) nounwind {