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
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 > >