On Fri, May 5, 2023 at 5:13 PM Palmer Dabbelt <pal...@dabbelt.com> wrote:
>
> On Fri, 05 May 2023 08:04:53 PDT (-0700), christoph.muell...@vrull.eu wrote:
> > What I forgot to mention:
> > Zfa is frozen and in public review:
> >   https://groups.google.com/a/groups.riscv.org/g/isa-dev/c/SED4ntBkabg
>
> Thanks, I'd also forgot to send that out ;).
>
> I think the only blocker here on the specification side is the assembly
> format for FLI?  It looks like the feedback on
> <https://github.com/riscv-non-isa/riscv-asm-manual/pull/85> has been
> pretty minor so far.  It'd be nice to have the docs lined up before
> we merge, but we could always just call it a GNU extension -- we've
> already got a lot of that in assembler land, so I don't think it's that
> big of a deal.

I also don't think that we need to wait for that PR to land.

Nelson already gave his ok on the Binutils v4 (but after ratification,
not freeze):
  https://sourceware.org/pipermail/binutils/2023-April/127027.html

FWIW, I have meanwhile sent out a v5 for Binutils as well (there were
few changes requested).
And the v5 has been rebased and retested as well.

>
> >
> > On Fri, May 5, 2023 at 5:03 PM Christoph Müllner
> > <christoph.muell...@vrull.eu> wrote:
> >>
> >> On Wed, Apr 19, 2023 at 11:58 AM Jin Ma <ji...@linux.alibaba.com> wrote:
> >> >
> >> > This patch adds the 'Zfa' extension for riscv, which is based on:
> >> >   https://github.com/riscv/riscv-isa-manual/commits/zfb
> >> >   
> >> > https://github.com/riscv/riscv-isa-manual/commit/1f038182810727f5feca311072e630d6baac51da
> >> >
> >> > The binutils-gdb for 'Zfa' extension:
> >> >   https://github.com/a4lg/binutils-gdb/commits/riscv-zfa
> >> >
> >> > What needs special explanation is:
> >> > 1, The immediate number of the instructions FLI.H/S/D is represented in 
> >> > the assembly as a
> >> >   floating-point value, with scientific counting when rs1 is 1,2, and 
> >> > decimal numbers for
> >> >   the rest.
> >> >
> >> >   Related llvm link:
> >> >     https://reviews.llvm.org/D145645
> >> >   Related discussion link:
> >> >     https://github.com/riscv/riscv-isa-manual/issues/980
> >> >
> >> > 2, According to riscv-spec, "The FCVTMO D.W.D instruction was added 
> >> > principally to
> >> >   accelerate the processing of JavaScript Numbers.", so it seems that no 
> >> > implementation
> >> >   is required.
> >> >
> >> > 3, The instructions FMINM and FMAXM correspond to C23 library function 
> >> > fminimum and fmaximum.
> >> >   Therefore, this patch has simply implemented the pattern of 
> >> > fminm<hf\sf\df>3 and
> >> >   fmaxm<hf\sf\df>3 to prepare for later.
> >> >
> >> > gcc/ChangeLog:
> >> >
> >> >         * common/config/riscv/riscv-common.cc: Add zfa extension version.
> >> >         * config/riscv/constraints.md (Zf): Constrain the floating point 
> >> > number that the
> >> >         instructions FLI.H/S/D can load.
> >> >         ((TARGET_XTHEADFMV || TARGET_ZFA) ? FP_REGS : NO_REGS): enable 
> >> > FMVP.D.X and FMVH.X.D.
> >> >         * config/riscv/iterators.md (ceil): New.
> >> >         * config/riscv/riscv-protos.h 
> >> > (riscv_float_const_rtx_index_for_fli): New.
> >> >         * config/riscv/riscv.cc (find_index_in_array): New.
> >> >         (riscv_float_const_rtx_index_for_fli): Get the index of the 
> >> > floating-point number that
> >> >         the instructions FLI.H/S/D can mov.
> >> >         (riscv_cannot_force_const_mem): If instruction FLI.H/S/D can be 
> >> > used, memory is not applicable.
> >> >         (riscv_const_insns): The cost of FLI.H/S/D is 3.
> >> >         (riscv_legitimize_const_move): Likewise.
> >> >         (riscv_split_64bit_move_p): If instruction FLI.H/S/D can be 
> >> > used, no split is required.
> >> >         (riscv_output_move): Output the mov instructions in zfa 
> >> > extension.
> >> >         (riscv_print_operand): Output the floating-point value of the 
> >> > FLI.H/S/D immediate in assembly
> >> >         (riscv_secondary_memory_needed): Likewise.
> >> >         * config/riscv/riscv.h (GP_REG_RTX_P): New.
> >> >         * config/riscv/riscv.md (fminm<mode>3): New.
> >> >
> >> > gcc/testsuite/ChangeLog:
> >> >
> >> >         * gcc.target/riscv/zfa-fleq-fltq-rv32.c: New test.
> >> >         * gcc.target/riscv/zfa-fleq-fltq.c: New test.
> >> >         * gcc.target/riscv/zfa-fli-rv32.c: New test.
> >> >         * gcc.target/riscv/zfa-fli-zfh-rv32.c: New test.
> >> >         * gcc.target/riscv/zfa-fli-zfh.c: New test.
> >> >         * gcc.target/riscv/zfa-fli.c: New test.
> >> >         * gcc.target/riscv/zfa-fmovh-fmovp-rv32.c: New test.
> >> >         * gcc.target/riscv/zfa-fround-rv32.c: New test.
> >> >         * gcc.target/riscv/zfa-fround.c: New test.
> >> > ---
> >> >  gcc/common/config/riscv/riscv-common.cc       |   4 +
> >> >  gcc/config/riscv/constraints.md               |  11 +-
> >> >  gcc/config/riscv/iterators.md                 |   5 +
> >> >  gcc/config/riscv/riscv-opts.h                 |   3 +
> >> >  gcc/config/riscv/riscv-protos.h               |   1 +
> >> >  gcc/config/riscv/riscv.cc                     | 168 +++++++++++++++++-
> >> >  gcc/config/riscv/riscv.h                      |   1 +
> >> >  gcc/config/riscv/riscv.md                     | 112 +++++++++---
> >> >  .../gcc.target/riscv/zfa-fleq-fltq-rv32.c     |  19 ++
> >> >  .../gcc.target/riscv/zfa-fleq-fltq.c          |  19 ++
> >> >  gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c |  79 ++++++++
> >> >  .../gcc.target/riscv/zfa-fli-zfh-rv32.c       |  41 +++++
> >> >  gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c  |  41 +++++
> >> >  gcc/testsuite/gcc.target/riscv/zfa-fli.c      |  79 ++++++++
> >> >  .../gcc.target/riscv/zfa-fmovh-fmovp-rv32.c   |  10 ++
> >> >  .../gcc.target/riscv/zfa-fround-rv32.c        |  42 +++++
> >> >  gcc/testsuite/gcc.target/riscv/zfa-fround.c   |  42 +++++
> >> >  17 files changed, 652 insertions(+), 25 deletions(-)
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c
> >> >  create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fround.c
> >> >
> >> > diff --git a/gcc/common/config/riscv/riscv-common.cc 
> >> > b/gcc/common/config/riscv/riscv-common.cc
> >> > index 309a52def75..f9fce6bcc38 100644
> >> > --- a/gcc/common/config/riscv/riscv-common.cc
> >> > +++ b/gcc/common/config/riscv/riscv-common.cc
> >> > @@ -217,6 +217,8 @@ static const struct riscv_ext_version 
> >> > riscv_ext_version_table[] =
> >> >    {"zfh",       ISA_SPEC_CLASS_NONE, 1, 0},
> >> >    {"zfhmin",    ISA_SPEC_CLASS_NONE, 1, 0},
> >> >
> >> > +  {"zfa",     ISA_SPEC_CLASS_NONE, 0, 2},
> >> > +
> >> >    {"zmmul", ISA_SPEC_CLASS_NONE, 1, 0},
> >> >
> >> >    {"svinval", ISA_SPEC_CLASS_NONE, 1, 0},
> >> > @@ -1260,6 +1262,8 @@ static const riscv_ext_flag_table_t 
> >> > riscv_ext_flag_table[] =
> >> >    {"zfhmin",    &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN},
> >> >    {"zfh",       &gcc_options::x_riscv_zf_subext, MASK_ZFH},
> >> >
> >> > +  {"zfa",       &gcc_options::x_riscv_zf_subext, MASK_ZFA},
> >> > +
> >> >    {"zmmul", &gcc_options::x_riscv_zm_subext, MASK_ZMMUL},
> >> >
> >> >    {"svinval", &gcc_options::x_riscv_sv_subext, MASK_SVINVAL},
> >> > diff --git a/gcc/config/riscv/constraints.md 
> >> > b/gcc/config/riscv/constraints.md
> >> > index c448e6b37e9..62d9094f966 100644
> >> > --- a/gcc/config/riscv/constraints.md
> >> > +++ b/gcc/config/riscv/constraints.md
> >> > @@ -118,6 +118,13 @@ (define_constraint "T"
> >> >    (and (match_operand 0 "move_operand")
> >> >         (match_test "CONSTANT_P (op)")))
> >> >
> >> > +;; Zfa constraints.
> >> > +
> >> > +(define_constraint "Zf"
> >> > +  "A floating point number that can be loaded using instruction `fli` 
> >> > in zfa."
> >> > +  (and (match_code "const_double")
> >> > +       (match_test "(riscv_float_const_rtx_index_for_fli (op) != -1)")))
> >> > +
> >> >  ;; Vector constraints.
> >> >
> >> >  (define_register_constraint "vr" "TARGET_VECTOR ? V_REGS : NO_REGS"
> >> > @@ -183,8 +190,8 @@ (define_memory_constraint "Wdm"
> >> >
> >> >  ;; Vendor ISA extension constraints.
> >> >
> >> > -(define_register_constraint "th_f_fmv" "TARGET_XTHEADFMV ? FP_REGS : 
> >> > NO_REGS"
> >> > +(define_register_constraint "th_f_fmv" "(TARGET_XTHEADFMV || 
> >> > TARGET_ZFA) ? FP_REGS : NO_REGS"
> >> >    "A floating-point register for XTheadFmv.")
> >> >
> >> > -(define_register_constraint "th_r_fmv" "TARGET_XTHEADFMV ? GR_REGS : 
> >> > NO_REGS"
> >> > +(define_register_constraint "th_r_fmv" "(TARGET_XTHEADFMV || 
> >> > TARGET_ZFA) ? GR_REGS : NO_REGS"
> >> >    "An integer register for XTheadFmv.")
> >>
> >> These are vendor extension constraints with the prefix "th_".
> >> I would avoid using them in code that targets standard extensions.
> >>
> >> I see two ways here:
> >> a) Create two new constraints at the top of the file. E.g.:
> >>     - "F" - "A floating-point register (no fall-back for Zfinx)" and
> >>     - "rF" - "A integer register in case FP registers are available".
> >> b) Move to top and rename these two constraints (and adjust
> >> movdf_hardfloat_rv32 accordingly)
> >>
> >> I would prefer b) and would even go so far, that I would do this in a
> >> separate commit that
> >> comes before the Zfa support patch.
> >>
> >>
> >> I've applied the patch on top of today's master (with --3way) and
> >> successfully tested it:
> >> Tested-by: Christoph Müllner <christoph.muell...@vrull.eu>
> >>
> >> > diff --git a/gcc/config/riscv/iterators.md 
> >> > b/gcc/config/riscv/iterators.md
> >> > index 9b767038452..c81b08e3cc5 100644
> >> > --- a/gcc/config/riscv/iterators.md
> >> > +++ b/gcc/config/riscv/iterators.md
> >> > @@ -288,3 +288,8 @@ (define_int_iterator QUIET_COMPARISON 
> >> > [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
> >> >  (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") 
> >> > (UNSPEC_FLE_QUIET "le")])
> >> >  (define_int_attr QUIET_PATTERN [(UNSPEC_FLT_QUIET "LT") 
> >> > (UNSPEC_FLE_QUIET "LE")])
> >> >
> >> > +(define_int_iterator ROUND [UNSPEC_ROUND UNSPEC_FLOOR UNSPEC_CEIL 
> >> > UNSPEC_BTRUNC UNSPEC_ROUNDEVEN UNSPEC_NEARBYINT])
> >> > +(define_int_attr round_pattern [(UNSPEC_ROUND "round") (UNSPEC_FLOOR 
> >> > "floor") (UNSPEC_CEIL "ceil")
> >> > +                               (UNSPEC_BTRUNC "btrunc") 
> >> > (UNSPEC_ROUNDEVEN "roundeven") (UNSPEC_NEARBYINT "nearbyint")])
> >> > +(define_int_attr round_rm [(UNSPEC_ROUND "rmm") (UNSPEC_FLOOR "rdn") 
> >> > (UNSPEC_CEIL "rup")
> >> > +                          (UNSPEC_BTRUNC "rtz") (UNSPEC_ROUNDEVEN 
> >> > "rne") (UNSPEC_NEARBYINT "dyn")])
> >> > \ No newline at end of file
> >> > diff --git a/gcc/config/riscv/riscv-opts.h 
> >> > b/gcc/config/riscv/riscv-opts.h
> >> > index cf0cd669be4..87b72efd12e 100644
> >> > --- a/gcc/config/riscv/riscv-opts.h
> >> > +++ b/gcc/config/riscv/riscv-opts.h
> >> > @@ -172,6 +172,9 @@ enum stack_protector_guard {
> >> >  #define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0)
> >> >  #define TARGET_ZFH    ((riscv_zf_subext & MASK_ZFH) != 0)
> >> >
> >> > +#define MASK_ZFA   (1 << 0)
> >> > +#define TARGET_ZFA    ((riscv_zf_subext & MASK_ZFA) != 0)
> >> > +
> >> >  #define MASK_ZMMUL      (1 << 0)
> >> >  #define TARGET_ZMMUL    ((riscv_zm_subext & MASK_ZMMUL) != 0)
> >> >
> >> > diff --git a/gcc/config/riscv/riscv-protos.h 
> >> > b/gcc/config/riscv/riscv-protos.h
> >> > index 5244e8dcbf0..e421244a06c 100644
> >> > --- a/gcc/config/riscv/riscv-protos.h
> >> > +++ b/gcc/config/riscv/riscv-protos.h
> >> > @@ -38,6 +38,7 @@ enum riscv_symbol_type {
> >> >  /* Routines implemented in riscv.cc.  */
> >> >  extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
> >> >  extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
> >> > +extern int riscv_float_const_rtx_index_for_fli (rtx);
> >> >  extern int riscv_regno_mode_ok_for_base_p (int, machine_mode, bool);
> >> >  extern int riscv_address_insns (rtx, machine_mode, bool);
> >> >  extern int riscv_const_insns (rtx);
> >> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> >> > index cdb47e81e7c..faffedffe97 100644
> >> > --- a/gcc/config/riscv/riscv.cc
> >> > +++ b/gcc/config/riscv/riscv.cc
> >> > @@ -799,6 +799,116 @@ static int riscv_symbol_insns (enum 
> >> > riscv_symbol_type type)
> >> >      }
> >> >  }
> >> >
> >> > +/* Immediate values loaded by the FLI.S instruction in Chapter 25 of 
> >> > the latest RISC-V ISA
> >> > +   Manual draft. For details, please see:
> >> > +   
> >> > https://github.com/riscv/riscv-isa-manual/releases/tag/draft-20221217-cb3b9d1
> >> >  */
> >> > +
> >> > +unsigned HOST_WIDE_INT fli_value_hf[32] =
> >> > +{
> >> > +  0xbc00, 0x400, 0x100, 0x200, 0x1c00, 0x2000, 0x2c00, 0x3000,
> >> > +  0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3a00, 0x3b00,
> >> > +  0x3c00, 0x3d00, 0x3e00, 0x3f00, 0x4000, 0x4100, 0x4200, 0x4400,
> >> > +  0x4800, 0x4c00, 0x5800, 0x5c00, 0x7800,
> >> > +  /* Only used for filling, ensuring that 29 and 30 of HF are the same. 
> >> > */
> >> > +  0x7800,
> >> > +  0x7c00, 0x7e00,
> >> > +};
> >> > +
> >> > +unsigned HOST_WIDE_INT fli_value_sf[32] =
> >> > +{
> >> > +  0xbf800000, 0x00800000, 0x37800000, 0x38000000, 0x3b800000, 
> >> > 0x3c000000, 0x3d800000, 0x3e000000,
> >> > +  0x3e800000, 0x3ea00000, 0x3ec00000, 0x3ee00000, 0x3f000000, 
> >> > 0x3f200000, 0x3f400000, 0x3f600000,
> >> > +  0x3f800000, 0x3fa00000, 0x3fc00000, 0x3fe00000, 0x40000000, 
> >> > 0x40200000, 0x40400000, 0x40800000,
> >> > +  0x41000000, 0x41800000, 0x43000000, 0x43800000, 0x47000000, 
> >> > 0x47800000, 0x7f800000, 0x7fc00000
> >> > +};
> >> > +
> >> > +unsigned HOST_WIDE_INT fli_value_df[32] =
> >> > +{
> >> > +  0xbff0000000000000, 0x10000000000000, 0x3ef0000000000000, 
> >> > 0x3f00000000000000,
> >> > +  0x3f70000000000000, 0x3f80000000000000, 0x3fb0000000000000, 
> >> > 0x3fc0000000000000,
> >> > +  0x3fd0000000000000, 0x3fd4000000000000, 0x3fd8000000000000, 
> >> > 0x3fdc000000000000,
> >> > +  0x3fe0000000000000, 0x3fe4000000000000, 0x3fe8000000000000, 
> >> > 0x3fec000000000000,
> >> > +  0x3ff0000000000000, 0x3ff4000000000000, 0x3ff8000000000000, 
> >> > 0x3ffc000000000000,
> >> > +  0x4000000000000000, 0x4004000000000000, 0x4008000000000000, 
> >> > 0x4010000000000000,
> >> > +  0x4020000000000000, 0x4030000000000000, 0x4060000000000000, 
> >> > 0x4070000000000000,
> >> > +  0x40e0000000000000, 0x40f0000000000000, 0x7ff0000000000000, 
> >> > 0x7ff8000000000000,
> >> > +};
> >> > +
> >> > +const char *fli_value_print[32] =
> >> > +{
> >> > +  "-1.0", "min", "1.52587890625e-05", "3.0517578125e-05", "0.00390625", 
> >> > "0.0078125", "0.0625", "0.125",
> >> > +  "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875",
> >> > +  "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0",
> >> > +  "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0", "inf", "nan"
> >> > +};
> >> > +
> >> > +/* Find the index of TARGET in ARRAY, and return -1 if not found. */
> >> > +
> >> > +static int
> >> > +find_index_in_array (unsigned HOST_WIDE_INT target, unsigned 
> >> > HOST_WIDE_INT *array, int len)
> >> > +{
> >> > +  if (array == NULL)
> >> > +    return -1;
> >> > +
> >> > +  for (int i = 0; i < len; i++)
> >> > +    {
> >> > +      if (target == array[i])
> >> > +       return i;
> >> > +    }
> >> > +  return -1;
> >> > +}
> >> > +
> >> > +/* Return index of the FLI instruction table if rtx X is an immediate 
> >> > constant that
> >> > +   can be moved using a single FLI instruction in zfa extension. -1 
> >> > otherwise. */
> >> > +
> >> > +int
> >> > +riscv_float_const_rtx_index_for_fli (rtx x)
> >> > +{
> >> > +  machine_mode mode = GET_MODE (x);
> >> > +
> >> > +  if (!TARGET_ZFA || mode == VOIDmode
> >> > +      || !CONST_DOUBLE_P(x)
> >> > +      || (mode == HFmode && !TARGET_ZFH)
> >> > +      || (mode == SFmode && !TARGET_HARD_FLOAT)
> >> > +      || (mode == DFmode && !TARGET_DOUBLE_FLOAT))
> >> > +    return -1;
> >> > +
> >> > +  if (!SCALAR_FLOAT_MODE_P (mode)
> >> > +      || GET_MODE_BITSIZE (mode).to_constant () > HOST_BITS_PER_WIDE_INT
> >> > +      /* Only support up to DF mode.  */
> >> > +      || GET_MODE_BITSIZE (mode).to_constant () > GET_MODE_BITSIZE 
> >> > (DFmode))
> >> > +    return -1;
> >> > +
> >> > +  unsigned HOST_WIDE_INT ival = 0;
> >> > +
> >> > +  long res[2];
> >> > +  real_to_target (res,
> >> > +                 CONST_DOUBLE_REAL_VALUE (x),
> >> > +                 REAL_MODE_FORMAT (mode));
> >> > +
> >> > +  if (mode == DFmode)
> >> > +    {
> >> > +      int order = BYTES_BIG_ENDIAN ? 1 : 0;
> >> > +      ival = zext_hwi (res[order], 32);
> >> > +      ival |= (zext_hwi (res[1 - order], 32) << 32);
> >> > +    }
> >> > +  else
> >> > +      ival = zext_hwi (res[0], 32);
> >> > +
> >> > +  switch (mode)
> >> > +    {
> >> > +      case SFmode:
> >> > +       return find_index_in_array (ival, fli_value_sf, 32);
> >> > +      case DFmode:
> >> > +       return find_index_in_array (ival, fli_value_df, 32);
> >> > +      case HFmode:
> >> > +       return find_index_in_array (ival, fli_value_hf, 32);
> >> > +      default:
> >> > +       break;
> >> > +    }
> >> > +  return -1;
> >> > +}
> >> > +
> >> >  /* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
> >> >
> >> >  static bool
> >> > @@ -826,6 +936,9 @@ riscv_cannot_force_const_mem (machine_mode mode 
> >> > ATTRIBUTE_UNUSED, rtx x)
> >> >    if (GET_CODE (x) == HIGH)
> >> >      return true;
> >> >
> >> > +  if (riscv_float_const_rtx_index_for_fli (x) != -1)
> >> > +   return true;
> >> > +
> >> >    split_const (x, &base, &offset);
> >> >    if (riscv_symbolic_constant_p (base, &type))
> >> >      {
> >> > @@ -1213,6 +1326,11 @@ riscv_const_insns (rtx x)
> >> >        }
> >> >
> >> >      case CONST_DOUBLE:
> >> > +      /* See if we can use FMV directly.  */
> >> > +      if (riscv_float_const_rtx_index_for_fli (x) != -1)
> >> > +       return 3;
> >> > +      /* Fall through.  */
> >> > +
> >> >      case CONST_VECTOR:
> >> >        /* We can use x0 to load floating-point zero.  */
> >> >        return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0;
> >> > @@ -1749,6 +1867,12 @@ riscv_legitimize_const_move (machine_mode mode, 
> >> > rtx dest, rtx src)
> >> >        return;
> >> >      }
> >> >
> >> > +  if (riscv_float_const_rtx_index_for_fli (src) != -1)
> >> > +    {
> >> > +      riscv_emit_set (dest, src);
> >> > +      return;
> >> > +    }
> >> > +
> >> >    /* Split moves of symbolic constants into high/low pairs.  */
> >> >    if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src, FALSE))
> >> >      {
> >> > @@ -2770,12 +2894,19 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
> >> >    if (TARGET_64BIT)
> >> >      return false;
> >> >
> >> > +  /* There is no need to split if the FLI instruction in the `Zfa` 
> >> > extension can be used. */
> >> > +  if (riscv_float_const_rtx_index_for_fli (src) != -1)
> >> > +    return false;
> >> > +
> >> >    /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special 
> >> > case
> >> >       of zeroing an FPR with FCVT.D.W.  */
> >> >    if (TARGET_DOUBLE_FLOAT
> >> >        && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
> >> >           || (FP_REG_RTX_P (dest) && MEM_P (src))
> >> >           || (FP_REG_RTX_P (src) && MEM_P (dest))
> >> > +         || (TARGET_ZFA
> >> > +             && ((FP_REG_RTX_P (dest) && GP_REG_RTX_P (src))
> >> > +             || (FP_REG_RTX_P (src) && GP_REG_RTX_P (dest))))
> >> >           || (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE 
> >> > (src)))))
> >> >      return false;
> >> >
> >> > @@ -2857,6 +2988,8 @@ riscv_output_move (rtx dest, rtx src)
> >> >           case 4:
> >> >             return "fmv.x.s\t%0,%1";
> >> >           case 8:
> >> > +           if (!TARGET_64BIT && TARGET_ZFA)
> >> > +             return "fmv.x.w\t%0,%1\n\tfmvh.x.d\t%N0,%1";
> >> >             return "fmv.x.d\t%0,%1";
> >> >           }
> >> >
> >> > @@ -2916,6 +3049,8 @@ riscv_output_move (rtx dest, rtx src)
> >> >               case 8:
> >> >                 if (TARGET_64BIT)
> >> >                   return "fmv.d.x\t%0,%z1";
> >> > +               else if (TARGET_ZFA && src != CONST0_RTX (mode))
> >> > +                 return "fmvp.d.x\t%0,%1,%N1";
> >> >                 /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w 
> >> > */
> >> >                 gcc_assert (src == CONST0_RTX (mode));
> >> >                 return "fcvt.d.w\t%0,x0";
> >> > @@ -2968,6 +3103,14 @@ riscv_output_move (rtx dest, rtx src)
> >> >           case 8:
> >> >             return "fld\t%0,%1";
> >> >           }
> >> > +
> >> > +      if (src_code == CONST_DOUBLE && 
> >> > (riscv_float_const_rtx_index_for_fli (src) != -1))
> >> > +       switch (width)
> >> > +         {
> >> > +           case 2: return "fli.h\t%0,%1";
> >> > +           case 4: return "fli.s\t%0,%1";
> >> > +           case 8: return "fli.d\t%0,%1";
> >> > +         }
> >> >      }
> >> >    if (dest_code == REG && GP_REG_P (REGNO (dest)) && src_code == 
> >> > CONST_POLY_INT)
> >> >      {
> >> > @@ -4349,6 +4492,7 @@ riscv_memmodel_needs_release_fence (enum memmodel 
> >> > model)
> >> >     'S' Print shift-index of single-bit mask OP.
> >> >     'T' Print shift-index of inverted single-bit mask OP.
> >> >     '~' Print w if TARGET_64BIT is true; otherwise not print anything.
> >> > +   'N'  Print next register.
> >> >
> >> >     Note please keep this list and the list in riscv.md in sync.  */
> >> >
> >> > @@ -4533,6 +4677,9 @@ riscv_print_operand (FILE *file, rtx op, int 
> >> > letter)
> >> >         output_addr_const (file, newop);
> >> >         break;
> >> >        }
> >> > +    case 'N':
> >> > +      fputs (reg_names[REGNO (op) + 1], file);
> >> > +      break;
> >> >      default:
> >> >        switch (code)
> >> >         {
> >> > @@ -4549,6 +4696,24 @@ riscv_print_operand (FILE *file, rtx op, int 
> >> > letter)
> >> >             output_address (mode, XEXP (op, 0));
> >> >           break;
> >> >
> >> > +       case CONST_DOUBLE:
> >> > +         {
> >> > +           if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
> >> > +             {
> >> > +               fputs (reg_names[GP_REG_FIRST], file);
> >> > +               break;
> >> > +             }
> >> > +
> >> > +           int fli_index = riscv_float_const_rtx_index_for_fli (op);
> >> > +           if (fli_index == -1 || fli_index > 31)
> >> > +             {
> >> > +               output_operand_lossage ("invalid use of '%%%c'", letter);
> >> > +               break;
> >> > +             }
> >> > +           asm_fprintf (file, "%s", fli_value_print[fli_index]);
> >> > +           break;
> >> > +         }
> >> > +
> >> >         default:
> >> >           if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
> >> >             fputs (reg_names[GP_REG_FIRST], file);
> >> > @@ -5897,7 +6062,8 @@ riscv_secondary_memory_needed (machine_mode mode, 
> >> > reg_class_t class1,
> >> >    return (!riscv_v_ext_vector_mode_p (mode)
> >> >           && GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
> >> >           && (class1 == FP_REGS) != (class2 == FP_REGS)
> >> > -         && !TARGET_XTHEADFMV);
> >> > +         && !TARGET_XTHEADFMV
> >> > +         && !TARGET_ZFA);
> >> >  }
> >> >
> >> >  /* Implement TARGET_REGISTER_MOVE_COST.  */
> >> > diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> >> > index 66fb07d6652..d438b281142 100644
> >> > --- a/gcc/config/riscv/riscv.h
> >> > +++ b/gcc/config/riscv/riscv.h
> >> > @@ -377,6 +377,7 @@ ASM_MISA_SPEC
> >> >  #define SIBCALL_REG_P(REGNO)   \
> >> >    TEST_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], REGNO)
> >> >
> >> > +#define GP_REG_RTX_P(X) (REG_P (X) && GP_REG_P (REGNO (X)))
> >> >  #define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
> >> >
> >> >  /* Use s0 as the frame pointer if it is so requested.  */
> >> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> >> > index bc384d9aedf..f22e71b5a3a 100644
> >> > --- a/gcc/config/riscv/riscv.md
> >> > +++ b/gcc/config/riscv/riscv.md
> >> > @@ -59,6 +59,15 @@ (define_c_enum "unspec" [
> >> >    UNSPEC_LROUND
> >> >    UNSPEC_FMIN
> >> >    UNSPEC_FMAX
> >> > +  UNSPEC_RINT
> >> > +  UNSPEC_ROUND
> >> > +  UNSPEC_FLOOR
> >> > +  UNSPEC_CEIL
> >> > +  UNSPEC_BTRUNC
> >> > +  UNSPEC_ROUNDEVEN
> >> > +  UNSPEC_NEARBYINT
> >> > +  UNSPEC_FMINM
> >> > +  UNSPEC_FMAXM
> >> >
> >> >    ;; Stack tie
> >> >    UNSPEC_TIE
> >> > @@ -1232,6 +1241,26 @@ (define_insn "neg<mode>2"
> >> >  ;;
> >> >  ;;  ....................
> >> >
> >> > +(define_insn "fminm<mode>3"
> >> > +  [(set (match_operand:ANYF                    0 "register_operand" 
> >> > "=f")
> >> > +       (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " 
> >> > f"))
> >> > +                     (use (match_operand:ANYF 2 "register_operand" " 
> >> > f"))]
> >> > +                    UNSPEC_FMINM))]
> >> > +  "TARGET_HARD_FLOAT && TARGET_ZFA"
> >> > +  "fminm.<fmt>\t%0,%1,%2"
> >> > +  [(set_attr "type" "fmove")
> >> > +   (set_attr "mode" "<UNITMODE>")])
> >> > +
> >> > +(define_insn "fmaxm<mode>3"
> >> > +  [(set (match_operand:ANYF                    0 "register_operand" 
> >> > "=f")
> >> > +       (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " 
> >> > f"))
> >> > +                     (use (match_operand:ANYF 2 "register_operand" " 
> >> > f"))]
> >> > +                    UNSPEC_FMAXM))]
> >> > +  "TARGET_HARD_FLOAT && TARGET_ZFA"
> >> > +  "fmaxm.<fmt>\t%0,%1,%2"
> >> > +  [(set_attr "type" "fmove")
> >> > +   (set_attr "mode" "<UNITMODE>")])
> >> > +
> >> >  (define_insn "fmin<mode>3"
> >> >    [(set (match_operand:ANYF                    0 "register_operand" 
> >> > "=f")
> >> >         (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " 
> >> > f"))
> >> > @@ -1508,13 +1537,13 @@ (define_expand "movhf"
> >> >  })
> >> >
> >> >  (define_insn "*movhf_hardfloat"
> >> > -  [(set (match_operand:HF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  
> >> > *r,*r,*m")
> >> > -       (match_operand:HF 1 "move_operand"         " 
> >> > f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
> >> > +  [(set (match_operand:HF 0 "nonimmediate_operand" "=f, 
> >> > f,f,f,m,m,*f,*r,  *r,*r,*m")
> >> > +       (match_operand:HF 1 "move_operand"         " 
> >> > f,Zf,G,m,f,G,*r,*f,*G*r,*m,*r"))]
> >> >    "TARGET_ZFHMIN
> >> >     && (register_operand (operands[0], HFmode)
> >> >         || reg_or_0_operand (operands[1], HFmode))"
> >> >    { return riscv_output_move (operands[0], operands[1]); }
> >> > -  [(set_attr "move_type" 
> >> > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> > +  [(set_attr "move_type" 
> >> > "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> >     (set_attr "mode" "HF")])
> >> >
> >> >  (define_insn "*movhf_softfloat"
> >> > @@ -1580,6 +1609,26 @@ (define_insn 
> >> > "l<rint_pattern><ANYF:mode><GPR:mode>2"
> >> >    [(set_attr "type" "fcvt")
> >> >     (set_attr "mode" "<ANYF:MODE>")])
> >> >
> >> > +(define_insn "<round_pattern><ANYF:mode>2"
> >> > +  [(set (match_operand:ANYF     0 "register_operand" "=f")
> >> > +       (unspec:ANYF
> >> > +           [(match_operand:ANYF 1 "register_operand" " f")]
> >> > +       ROUND))]
> >> > +  "TARGET_HARD_FLOAT && TARGET_ZFA"
> >> > +  "fround.<ANYF:fmt>\t%0,%1,<round_rm>"
> >> > +  [(set_attr "type" "fcvt")
> >> > +   (set_attr "mode" "<ANYF:MODE>")])
> >> > +
> >> > +(define_insn "rint<ANYF:mode>2"
> >> > +  [(set (match_operand:ANYF     0 "register_operand" "=f")
> >> > +       (unspec:ANYF
> >> > +           [(match_operand:ANYF 1 "register_operand" " f")]
> >> > +       UNSPEC_RINT))]
> >> > +  "TARGET_HARD_FLOAT && TARGET_ZFA"
> >> > +  "froundnx.<ANYF:fmt>\t%0,%1"
> >> > +  [(set_attr "type" "fcvt")
> >> > +   (set_attr "mode" "<ANYF:MODE>")])
> >> > +
> >> >  ;;
> >> >  ;;  ....................
> >> >  ;;
> >> > @@ -1839,13 +1888,13 @@ (define_expand "movsf"
> >> >  })
> >> >
> >> >  (define_insn "*movsf_hardfloat"
> >> > -  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  
> >> > *r,*r,*m")
> >> > -       (match_operand:SF 1 "move_operand"         " 
> >> > f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
> >> > +  [(set (match_operand:SF 0 "nonimmediate_operand" "=f, 
> >> > f,f,f,m,m,*f,*r,  *r,*r,*m")
> >> > +       (match_operand:SF 1 "move_operand"         " 
> >> > f,Zf,G,m,f,G,*r,*f,*G*r,*m,*r"))]
> >> >    "TARGET_HARD_FLOAT
> >> >     && (register_operand (operands[0], SFmode)
> >> >         || reg_or_0_operand (operands[1], SFmode))"
> >> >    { return riscv_output_move (operands[0], operands[1]); }
> >> > -  [(set_attr "move_type" 
> >> > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> > +  [(set_attr "move_type" 
> >> > "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> >     (set_attr "mode" "SF")])
> >> >
> >> >  (define_insn "*movsf_softfloat"
> >> > @@ -1873,23 +1922,23 @@ (define_expand "movdf"
> >> >  ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
> >> >  ;; (However, we can still use fcvt.d.w to zero a floating-point 
> >> > register.)
> >> >  (define_insn "*movdf_hardfloat_rv32"
> >> > -  [(set (match_operand:DF 0 "nonimmediate_operand" 
> >> > "=f,f,f,m,m,*th_f_fmv,*th_r_fmv,  *r,*r,*m")
> >> > -       (match_operand:DF 1 "move_operand"         " 
> >> > f,G,m,f,G,*th_r_fmv,*th_f_fmv,*r*G,*m,*r"))]
> >> > +  [(set (match_operand:DF 0 "nonimmediate_operand" "=f, 
> >> > f,f,f,m,m,*th_f_fmv,*th_r_fmv,  *r,*r,*m")
> >> > +       (match_operand:DF 1 "move_operand"         " 
> >> > f,Zf,G,m,f,G,*th_r_fmv,*th_f_fmv,*r*G,*m,*r"))]
> >> >    "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
> >> >     && (register_operand (operands[0], DFmode)
> >> >         || reg_or_0_operand (operands[1], DFmode))"
> >> >    { return riscv_output_move (operands[0], operands[1]); }
> >> > -  [(set_attr "move_type" 
> >> > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> > +  [(set_attr "move_type" 
> >> > "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> >     (set_attr "mode" "DF")])
> >> >
> >> >  (define_insn "*movdf_hardfloat_rv64"
> >> > -  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  
> >> > *r,*r,*m")
> >> > -       (match_operand:DF 1 "move_operand"         " 
> >> > f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
> >> > +  [(set (match_operand:DF 0 "nonimmediate_operand" "=f, 
> >> > f,f,f,m,m,*f,*r,  *r,*r,*m")
> >> > +       (match_operand:DF 1 "move_operand"         " 
> >> > f,Zf,G,m,f,G,*r,*f,*r*G,*m,*r"))]
> >> >    "TARGET_64BIT && TARGET_DOUBLE_FLOAT
> >> >     && (register_operand (operands[0], DFmode)
> >> >         || reg_or_0_operand (operands[1], DFmode))"
> >> >    { return riscv_output_move (operands[0], operands[1]); }
> >> > -  [(set_attr "move_type" 
> >> > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> > +  [(set_attr "move_type" 
> >> > "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> >> >     (set_attr "mode" "DF")])
> >> >
> >> >  (define_insn "*movdf_softfloat"
> >> > @@ -2494,16 +2543,23 @@ (define_expand 
> >> > "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
> >> >    rtx op0 = operands[0];
> >> >    rtx op1 = operands[1];
> >> >    rtx op2 = operands[2];
> >> > -  rtx tmp = gen_reg_rtx (SImode);
> >> > -  rtx cmp = gen_rtx_<QUIET_PATTERN> (<X:MODE>mode, op1, op2);
> >> > -  rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, 
> >> > const0_rtx),
> >> > -                                        UNSPECV_FRFLAGS);
> >> > -  rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
> >> > -                                        UNSPECV_FSFLAGS);
> >> > -
> >> > -  emit_insn (gen_rtx_SET (tmp, frflags));
> >> > -  emit_insn (gen_rtx_SET (op0, cmp));
> >> > -  emit_insn (fsflags);
> >> > +
> >> > +  if (TARGET_ZFA)
> >> > +    emit_insn (gen_f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa(op0, 
> >> > op1, op2));
> >> > +  else
> >> > +    {
> >> > +      rtx tmp = gen_reg_rtx (SImode);
> >> > +      rtx cmp = gen_rtx_<QUIET_PATTERN> (<X:MODE>mode, op1, op2);
> >> > +      rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, 
> >> > const0_rtx),
> >> > +                                            UNSPECV_FRFLAGS);
> >> > +      rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
> >> > +                                            UNSPECV_FSFLAGS);
> >> > +
> >> > +      emit_insn (gen_rtx_SET (tmp, frflags));
> >> > +      emit_insn (gen_rtx_SET (op0, cmp));
> >> > +      emit_insn (fsflags);
> >> > +    }
> >> > +
> >> >    if (HONOR_SNANS (<ANYF:MODE>mode))
> >> >      emit_insn (gen_rtx_UNSPEC_VOLATILE (<ANYF:MODE>mode,
> >> >                                         gen_rtvec (2, op1, op2),
> >> > @@ -2511,6 +2567,18 @@ (define_expand 
> >> > "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
> >> >    DONE;
> >> >  })
> >> >
> >> > +(define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa"
> >> > +   [(set (match_operand:X      0 "register_operand" "=r")
> >> > +        (unspec:X
> >> > +         [(match_operand:ANYF 1 "register_operand" " f")
> >> > +          (match_operand:ANYF 2 "register_operand" " f")]
> >> > +         QUIET_COMPARISON))]
> >> > +  "TARGET_HARD_FLOAT && TARGET_ZFA"
> >> > +  "f<quiet_pattern>q.<fmt>\t%0,%1,%2"
> >> > +  [(set_attr "type" "fcmp")
> >> > +   (set_attr "mode" "<UNITMODE>")
> >> > +   (set (attr "length") (const_int 16))])
> >> > +
> >> >  (define_insn "*seq_zero_<X:mode><GPR:mode>"
> >> >    [(set (match_operand:GPR       0 "register_operand" "=r")
> >> >         (eq:GPR (match_operand:X 1 "register_operand" " r")
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c
> >> > new file mode 100644
> >> > index 00000000000..26895b76fa4
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c
> >> > @@ -0,0 +1,19 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O2" } */
> >> > +
> >> > +extern void abort(void);
> >> > +extern float a, b;
> >> > +extern double c, d;
> >> > +
> >> > +void
> >> > +foo()
> >> > +{
> >> > +  if ((__builtin_isless(a, b) ||  __builtin_islessequal(c, d))
> >> > +      && (__builtin_islessequal(a, b)|| __builtin_isless(c, d)))
> >> > +    abort();
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fleq.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fltq.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fleq.d" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fltq.d" 1 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c
> >> > new file mode 100644
> >> > index 00000000000..4ccd6a7dd78
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c
> >> > @@ -0,0 +1,19 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O2" } */
> >> > +
> >> > +extern void abort(void);
> >> > +extern float a, b;
> >> > +extern double c, d;
> >> > +
> >> > +void
> >> > +foo()
> >> > +{
> >> > +  if ((__builtin_isless(a, b) ||  __builtin_islessequal(c, d))
> >> > +      && (__builtin_islessequal(a, b)|| __builtin_isless(c, d)))
> >> > +    abort();
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fleq.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fltq.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fleq.d" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fltq.d" 1 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c
> >> > new file mode 100644
> >> > index 00000000000..c4da04797aa
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c
> >> > @@ -0,0 +1,79 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O0" } */
> >> > +
> >> > +void foo_float32 ()
> >> > +{
> >> > +  volatile float a;
> >> > +  a = -1.0;
> >> > +  a = 1.1754944e-38;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inff ();
> >> > +  a = __builtin_nanf ("");
> >> > +}
> >> > +
> >> > +void foo_double64 ()
> >> > +{
> >> > +  volatile double a;
> >> > +  a = -1.0;
> >> > +  a = 2.2250738585072014E-308;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inf ();
> >> > +  a = __builtin_nan ("");
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fli.s" 32 } } */
> >> > +/* { dg-final { scan-assembler-times "fli.d" 32 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c
> >> > new file mode 100644
> >> > index 00000000000..bcffe9d2c82
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c
> >> > @@ -0,0 +1,41 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv32imafdc_zfa_zfh -mabi=ilp32d -O0" } */
> >> > +
> >> > +void foo_float16 ()
> >> > +{
> >> > +  volatile _Float16 a;
> >> > +  a = -1.0;
> >> > +  a = 6.104E-5;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inff16 ();
> >> > +  a = __builtin_nanf16 ("");
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fli.h" 32 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c
> >> > new file mode 100644
> >> > index 00000000000..13aa7b5f846
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c
> >> > @@ -0,0 +1,41 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv64imafdc_zfa_zfh -mabi=lp64d -O0" } */
> >> > +
> >> > +void foo_float16 ()
> >> > +{
> >> > +  volatile _Float16 a;
> >> > +  a = -1.0;
> >> > +  a = 6.104E-5;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inff16 ();
> >> > +  a = __builtin_nanf16 ("");
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fli.h" 32 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fli.c
> >> > new file mode 100644
> >> > index 00000000000..b6d41cf460f
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli.c
> >> > @@ -0,0 +1,79 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O0" } */
> >> > +
> >> > +void foo_float32 ()
> >> > +{
> >> > +  volatile float a;
> >> > +  a = -1.0;
> >> > +  a = 1.1754944e-38;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inff ();
> >> > +  a = __builtin_nanf ("");
> >> > +}
> >> > +
> >> > +void foo_double64 ()
> >> > +{
> >> > +  volatile double a;
> >> > +  a = -1.0;
> >> > +  a = 2.2250738585072014E-308;
> >> > +  a = 1.0/(1 << 16);
> >> > +  a = 1.0/(1 << 15);
> >> > +  a = 1.0/(1 << 8);
> >> > +  a = 1.0/(1 << 7);
> >> > +  a = 1.0/(1 << 4);
> >> > +  a = 1.0/(1 << 3);
> >> > +  a = 1.0/(1 << 2);
> >> > +  a = 0.3125;
> >> > +  a = 0.375;
> >> > +  a = 0.4375;
> >> > +  a = 0.5;
> >> > +  a = 0.625;
> >> > +  a = 0.75;
> >> > +  a = 0.875;
> >> > +  a = 1.0;
> >> > +  a = 1.25;
> >> > +  a = 1.5;
> >> > +  a = 1.75;
> >> > +  a = 2.0;
> >> > +  a = 2.5;
> >> > +  a = 3.0;
> >> > +  a = 1.0*(1 << 2);
> >> > +  a = 1.0*(1 << 3);
> >> > +  a = 1.0*(1 << 4);
> >> > +  a = 1.0*(1 << 7);
> >> > +  a = 1.0*(1 << 8);
> >> > +  a = 1.0*(1 << 15);
> >> > +  a = 1.0*(1 << 16);
> >> > +  a = __builtin_inf ();
> >> > +  a = __builtin_nan ("");
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fli.s" 32 } } */
> >> > +/* { dg-final { scan-assembler-times "fli.d" 32 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c
> >> > new file mode 100644
> >> > index 00000000000..5a52adce36a
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c
> >> > @@ -0,0 +1,10 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv32g_zfa -mabi=ilp32 -O0" } */
> >> > +
> >> > +double foo(long long a)
> >> > +{
> >> > +  return (double)(a + 3);
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fmvp.d.x" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "fmvh.x.d" 1 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c
> >> > new file mode 100644
> >> > index 00000000000..b53601d6e1f
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c
> >> > @@ -0,0 +1,42 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O2" } */
> >> > +
> >> > +extern float a;
> >> > +extern double b;
> >> > +
> >> > +void foo (float *x, double *y)
> >> > +{
> >> > +  {
> >> > +    *x = __builtin_roundf (a);
> >> > +    *y = __builtin_round (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_floorf (a);
> >> > +    *y = __builtin_floor (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_ceilf (a);
> >> > +    *y = __builtin_ceil (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_truncf (a);
> >> > +    *y = __builtin_trunc (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_roundevenf (a);
> >> > +    *y = __builtin_roundeven (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_nearbyintf (a);
> >> > +    *y = __builtin_nearbyint (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_rintf (a);
> >> > +    *y = __builtin_rint (b);
> >> > +  }
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fround.s" 6 } } */
> >> > +/* { dg-final { scan-assembler-times "fround.d" 6 } } */
> >> > +/* { dg-final { scan-assembler-times "froundnx.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "froundnx.d" 1 } } */
> >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fround.c 
> >> > b/gcc/testsuite/gcc.target/riscv/zfa-fround.c
> >> > new file mode 100644
> >> > index 00000000000..c10de82578e
> >> > --- /dev/null
> >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fround.c
> >> > @@ -0,0 +1,42 @@
> >> > +/* { dg-do compile } */
> >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O2" } */
> >> > +
> >> > +extern float a;
> >> > +extern double b;
> >> > +
> >> > +void foo (float *x, double *y)
> >> > +{
> >> > +  {
> >> > +    *x = __builtin_roundf (a);
> >> > +    *y = __builtin_round (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_floorf (a);
> >> > +    *y = __builtin_floor (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_ceilf (a);
> >> > +    *y = __builtin_ceil (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_truncf (a);
> >> > +    *y = __builtin_trunc (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_roundevenf (a);
> >> > +    *y = __builtin_roundeven (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_nearbyintf (a);
> >> > +    *y = __builtin_nearbyint (b);
> >> > +  }
> >> > +  {
> >> > +    *x = __builtin_rintf (a);
> >> > +    *y = __builtin_rint (b);
> >> > +  }
> >> > +}
> >> > +
> >> > +/* { dg-final { scan-assembler-times "fround.s" 6 } } */
> >> > +/* { dg-final { scan-assembler-times "fround.d" 6 } } */
> >> > +/* { dg-final { scan-assembler-times "froundnx.s" 1 } } */
> >> > +/* { dg-final { scan-assembler-times "froundnx.d" 1 } } */
> >> > --
> >> > 2.17.1
> >> >

Reply via email to