diff mbox series

RISC-V: Support RVV floating-point ternary auto-vectorization

Message ID 20230621111252.236515-1-juzhe.zhong@rivai.ai
State New
Headers show
Series RISC-V: Support RVV floating-point ternary auto-vectorization | expand

Commit Message

juzhe.zhong@rivai.ai June 21, 2023, 11:12 a.m. UTC
This patch adds RVV floating-point auto-vectorization.
Also, fix attribute bug of floating-point ternary operations in vector.md.

gcc/ChangeLog:

        * config/riscv/autovec.md (fma<mode>4): New pattern.
        (*fma<mode>): Ditto.
        (fnma<mode>4): Ditto.
        (*fnma<mode>): Ditto.
        (fms<mode>4): Ditto.
        (*fms<mode>): Ditto.
        (fnms<mode>4): Ditto.
        (*fnms<mode>): Ditto.
        * config/riscv/riscv-protos.h (emit_vlmax_fp_ternary_insn): New function.
        * config/riscv/riscv-v.cc (emit_vlmax_fp_ternary_insn): Ditto.
        * config/riscv/vector.md: Fix attribute bug.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/autovec/ternop/ternop-1.c: Add floating-point teranary tests.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-2.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-3.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-4.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-5.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-6.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c: Ditto.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-10.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-11.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-12.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-7.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-8.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop-9.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c: New test.
        * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c: New test.

---
 gcc/config/riscv/autovec.md                   | 180 ++++++++++++++++++
 gcc/config/riscv/riscv-protos.h               |   1 +
 gcc/config/riscv/riscv-v.cc                   |  21 ++
 gcc/config/riscv/vector.md                    |   4 +-
 .../riscv/rvv/autovec/ternop/ternop-1.c       |   8 +-
 .../riscv/rvv/autovec/ternop/ternop-10.c      |  23 +++
 .../riscv/rvv/autovec/ternop/ternop-11.c      |  29 +++
 .../riscv/rvv/autovec/ternop/ternop-12.c      |  28 +++
 .../riscv/rvv/autovec/ternop/ternop-2.c       |   8 +-
 .../riscv/rvv/autovec/ternop/ternop-3.c       |   9 +-
 .../riscv/rvv/autovec/ternop/ternop-4.c       |   8 +-
 .../riscv/rvv/autovec/ternop/ternop-5.c       |   8 +-
 .../riscv/rvv/autovec/ternop/ternop-6.c       |   9 +-
 .../riscv/rvv/autovec/ternop/ternop-7.c       |  23 +++
 .../riscv/rvv/autovec/ternop/ternop-8.c       |  29 +++
 .../riscv/rvv/autovec/ternop/ternop-9.c       |  28 +++
 .../riscv/rvv/autovec/ternop/ternop_run-1.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-10.c  |  40 ++++
 .../riscv/rvv/autovec/ternop/ternop_run-11.c  |  60 ++++++
 .../riscv/rvv/autovec/ternop/ternop_run-12.c  |  60 ++++++
 .../riscv/rvv/autovec/ternop/ternop_run-2.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-3.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-4.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-5.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-6.c   |  12 +-
 .../riscv/rvv/autovec/ternop/ternop_run-7.c   |  40 ++++
 .../riscv/rvv/autovec/ternop/ternop_run-8.c   |  60 ++++++
 .../riscv/rvv/autovec/ternop/ternop_run-9.c   |  60 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-1.c    |  35 ++++
 .../rvv/autovec/ternop/ternop_run_zvfh-10.c   |  35 ++++
 .../rvv/autovec/ternop/ternop_run_zvfh-11.c   |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-12.c   |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-2.c    |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-3.c    |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-4.c    |  35 ++++
 .../rvv/autovec/ternop/ternop_run_zvfh-5.c    |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-6.c    |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-7.c    |  35 ++++
 .../rvv/autovec/ternop/ternop_run_zvfh-8.c    |  55 ++++++
 .../rvv/autovec/ternop/ternop_run_zvfh-9.c    |  55 ++++++
 40 files changed, 1366 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c

Comments

Robin Dapp June 21, 2023, 12:54 p.m. UTC | #1
Hi Juzhe,

LGTM apart from a tiny nit:

> +  /* We have a maximum of 11 operands for RVV instruction patterns according to
> +   * vector.md.  */
> +  insn_expander<11> e (/*OP_NUM*/ op_num, /*HAS_DEST_P*/ true,

Seems like you copied this from the non-fp ternary part but the
rest of the file uses RVV_INSN_OPERANDS_MAX already.  Could you adjust this
as well as emit_vlmax_ternary_insn?

Thanks.

Regards
 Robin
Jeff Law June 21, 2023, 3:15 p.m. UTC | #2
On 6/21/23 05:12, Juzhe-Zhong wrote:
> This patch adds RVV floating-point auto-vectorization.
> Also, fix attribute bug of floating-point ternary operations in vector.md.
> 
> gcc/ChangeLog:
> 
>          * config/riscv/autovec.md (fma<mode>4): New pattern.
>          (*fma<mode>): Ditto.
>          (fnma<mode>4): Ditto.
>          (*fnma<mode>): Ditto.
>          (fms<mode>4): Ditto.
>          (*fms<mode>): Ditto.
>          (fnms<mode>4): Ditto.
>          (*fnms<mode>): Ditto.
>          * config/riscv/riscv-protos.h (emit_vlmax_fp_ternary_insn): New function.
>          * config/riscv/riscv-v.cc (emit_vlmax_fp_ternary_insn): Ditto.
>          * config/riscv/vector.md: Fix attribute bug.
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-1.c: Add floating-point teranary tests.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-2.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-3.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-4.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-5.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-6.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-9.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c: New test.
> 
> ---


> +
> +(define_insn_and_split "*fma<mode>"
> +  [(set (match_operand:VF_AUTO 0 "register_operand"   "=vr, vr, ?&vr")
> +	(fma:VF_AUTO
> +	  (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
> +	  (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
> +	  (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr")))
> +   (clobber (match_scratch:SI 4 "=r,r,r"))]
> +  "TARGET_VECTOR"
> +  "#"
> +  "&& reload_completed"
> +  [(const_int 0)]
> +  {
> +    PUT_MODE (operands[4], Pmode);
Maybe this has already been answered, but why not get the mode right in 
the expander & pattern as opposed to blindly changing it in the C fragment?

It's probably technically safe to do what you've done, mostly because by 
the time the C code runs, we've turned the scratch into a hard register 
and I suspect the code to allocate scratches probably constructs a new 
hard reg for each scratch rather than using a shared object.

But if we can, let's get the mode right from the beginning.

I'll note the existing define_insn_and_splits for integer FMAs have this 
same wart.


jeff
juzhe.zhong@rivai.ai June 21, 2023, 3:20 p.m. UTC | #3
I failed to make Pmode of the of operand.

I have tried the following

clobber (match_dup_4)
But it causes to many issues. I do many tries turns out only the current solution can work.



juzhe.zhong@rivai.ai
 
From: Jeff Law
Date: 2023-06-21 23:15
To: Juzhe-Zhong; gcc-patches
CC: kito.cheng; kito.cheng; palmer; palmer; rdapp.gcc
Subject: Re: [PATCH] RISC-V: Support RVV floating-point ternary auto-vectorization
 
 
On 6/21/23 05:12, Juzhe-Zhong wrote:
> This patch adds RVV floating-point auto-vectorization.
> Also, fix attribute bug of floating-point ternary operations in vector.md.
> 
> gcc/ChangeLog:
> 
>          * config/riscv/autovec.md (fma<mode>4): New pattern.
>          (*fma<mode>): Ditto.
>          (fnma<mode>4): Ditto.
>          (*fnma<mode>): Ditto.
>          (fms<mode>4): Ditto.
>          (*fms<mode>): Ditto.
>          (fnms<mode>4): Ditto.
>          (*fnms<mode>): Ditto.
>          * config/riscv/riscv-protos.h (emit_vlmax_fp_ternary_insn): New function.
>          * config/riscv/riscv-v.cc (emit_vlmax_fp_ternary_insn): Ditto.
>          * config/riscv/vector.md: Fix attribute bug.
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-1.c: Add floating-point teranary tests.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-2.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-3.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-4.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-5.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-6.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c: Ditto.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop-9.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c: New test.
>          * gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c: New test.
> 
> ---
 
 
> +
> +(define_insn_and_split "*fma<mode>"
> +  [(set (match_operand:VF_AUTO 0 "register_operand"   "=vr, vr, ?&vr")
> + (fma:VF_AUTO
> +   (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
> +   (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
> +   (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr")))
> +   (clobber (match_scratch:SI 4 "=r,r,r"))]
> +  "TARGET_VECTOR"
> +  "#"
> +  "&& reload_completed"
> +  [(const_int 0)]
> +  {
> +    PUT_MODE (operands[4], Pmode);
Maybe this has already been answered, but why not get the mode right in 
the expander & pattern as opposed to blindly changing it in the C fragment?
 
It's probably technically safe to do what you've done, mostly because by 
the time the C code runs, we've turned the scratch into a hard register 
and I suspect the code to allocate scratches probably constructs a new 
hard reg for each scratch rather than using a shared object.
 
But if we can, let's get the mode right from the beginning.
 
I'll note the existing define_insn_and_splits for integer FMAs have this 
same wart.
 
 
jeff
Jeff Law June 21, 2023, 3:21 p.m. UTC | #4
On 6/21/23 09:20, 钟居哲 wrote:
> I failed to make Pmode of the of operand.
> 
> I have tried the following
> 
> clobber (match_dup_4)
> But it causes to many issues. I do many tries turns out only the current 
> solution can work.
Can you describe more concretely what failed?

Offhand I can't think of a reason why this shouldn't work and what 
you're doing seems long term fragile/wrong.

jeff
juzhe.zhong@rivai.ai June 21, 2023, 3:28 p.m. UTC | #5
I have tried:
(define_expand "fms<mode>4"
  [(parallel
    [(set (match_operand:VF_AUTO 0 "register_operand")
    (fma:VF_AUTO
      (match_operand:VF_AUTO 1 "register_operand")
      (match_operand:VF_AUTO 2 "register_operand")
      (neg:VF_AUTO
        (match_operand:VF_AUTO 3 "register_operand"))))
     (clobber (match_dup 4))])]
  "TARGET_VECTOR"
  {
operands[4] = gen_reg_rtx (Pmode);
})

(define_insn_and_split "*fms<VF_AUTO:mode><P:mode>"
  [(set (match_operand:VF_AUTO 0 "register_operand"     "=vr, vr, ?&vr")
  (fma:VF_AUTO
    (match_operand:VF_AUTO 1 "register_operand"   " %0, vr,   vr")
    (match_operand:VF_AUTO 2 "register_operand"   " vr, vr,   vr")
    (neg:VF_AUTO
      (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr"))))
   (clobber (match_operand:P 4 "=r,r,r"))]
  "TARGET_VECTOR"
  "#"
  "&& reload_completed"
  [(const_int 0)]
  {
    riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
    if (which_alternative == 2)
      emit_insn (gen_rtx_SET (operands[0], operands[3]));
    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (MINUS, <MODE>mode),
                riscv_vector::RVV_TERNOP, ops, operands[4]);
    DONE;
  }
  [(set_attr "type" "vfmuladd")
   (set_attr "mode" "<MODE>")])

It fails and create ICE.


juzhe.zhong@rivai.ai
 
From: Jeff Law
Date: 2023-06-21 23:21
To: 钟居哲; gcc-patches
CC: kito.cheng; kito.cheng; palmer; palmer; rdapp.gcc
Subject: Re: [PATCH] RISC-V: Support RVV floating-point ternary auto-vectorization
 
 
On 6/21/23 09:20, 钟居哲 wrote:
> I failed to make Pmode of the of operand.
> 
> I have tried the following
> 
> clobber (match_dup_4)
> But it causes to many issues. I do many tries turns out only the current 
> solution can work.
Can you describe more concretely what failed?
 
Offhand I can't think of a reason why this shouldn't work and what 
you're doing seems long term fragile/wrong.
 
jeff
Jeff Law June 21, 2023, 3:32 p.m. UTC | #6
On 6/21/23 09:28, 钟居哲 wrote:
> I have tried:
> (define_expand "fms<mode>4"
>    [(parallel
>      [(set (match_operand:VF_AUTO 0 "register_operand")
>      (fma:VF_AUTO
>        (match_operand:VF_AUTO 1 "register_operand")
>        (match_operand:VF_AUTO 2 "register_operand")
>        (neg:VF_AUTO
>          (match_operand:VF_AUTO 3 "register_operand"))))
>       (clobber (match_dup4))])]
> "TARGET_VECTOR"
>    {
> operands[4] = gen_reg_rtx (Pmode);
> })
> 
> (define_insn_and_split "*fms<VF_AUTO:mode><P:mode>"
>    [(set (match_operand:VF_AUTO 0 "register_operand" "=vr, vr, ?&vr")
>    (fma:VF_AUTO
>      (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
>      (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
>      (neg:VF_AUTO
>        (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr"))))
>     (clobber (match_operand:P 4 "=r,r,r"))]
> "TARGET_VECTOR"
> "#"
> "&& reload_completed"
>    [(const_int 0)]
>    {
>      riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
>      if (which_alternative == 2)
>        emit_insn (gen_rtx_SET (operands[0], operands[3]));
>      rtx ops[] = {operands[0], operands[1], operands[2], operands[3], 
> operands[0]};
>      riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (MINUS, 
> <MODE>mode),
>                  riscv_vector::RVV_TERNOP, ops, operands[4]);
>      DONE;
>    }
>    [(set_attr "type" "vfmuladd")
>     (set_attr "mode" "<MODE>")])
> 
> It fails and create ICE.
But where did ICE and *why*?  That's really the question.  Changing the 
mode just looks like papering over a more serious issue.

jeff
juzhe.zhong@rivai.ai June 21, 2023, 3:55 p.m. UTC | #7
Hi, Jeff.

I tried again:
+(define_expand "fma<mode>4"
+  [(parallel
+    [(set (match_operand:VF_AUTO 0 "register_operand")
+	  (fma:VF_AUTO
+	    (match_operand:VF_AUTO 1 "register_operand")
+	    (match_operand:VF_AUTO 2 "register_operand")
+	    (match_operand:VF_AUTO 3 "register_operand")))
+     (clobber (match_dup 4))])]
+  "TARGET_VECTOR"
+  {
+    operands[4] = gen_reg_rtx (Pmode);
+  })
+
+(define_insn_and_split "*fma<VF_AUTO:mode><P:mode>"
+  [(set (match_operand:VF_AUTO 0 "register_operand"   "=vr, vr, ?&vr")
+	(fma:VF_AUTO
+	  (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
+	  (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
+	  (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr")))
+   (clobber (match_operand:P 4 "register_operand" "=r,r,r"))]
+  "TARGET_VECTOR"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    riscv_vector::emit_vlmax_vsetvl (<VF_AUTO:MODE>mode, operands[4]);
+    if (which_alternative == 2)
+      emit_insn (gen_rtx_SET (operands[0], operands[3]));
+    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
+    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (PLUS, <VF_AUTO:MODE>mode),
+					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    DONE;
+  }
+  [(set_attr "type" "vfmuladd")
+   (set_attr "mode" "<VF_AUTO:MODE>")])
It seems to work and all test have passed.
Thanks for pointing this out.

I have sent V3:
https://gcc.gnu.org/pipermail/gcc-patches/2023-June/622481.html 

If this implementation is more reasonable, I will send a separate patch to adjust integer ternary autovec patterns.


juzhe.zhong@rivai.ai
 
From: Jeff Law
Date: 2023-06-21 23:32
To: 钟居哲; gcc-patches
CC: kito.cheng; kito.cheng; palmer; palmer; rdapp.gcc
Subject: Re: [PATCH] RISC-V: Support RVV floating-point ternary auto-vectorization
 
 
On 6/21/23 09:28, 钟居哲 wrote:
> I have tried:
> (define_expand "fms<mode>4"
>    [(parallel
>      [(set (match_operand:VF_AUTO 0 "register_operand")
>      (fma:VF_AUTO
>        (match_operand:VF_AUTO 1 "register_operand")
>        (match_operand:VF_AUTO 2 "register_operand")
>        (neg:VF_AUTO
>          (match_operand:VF_AUTO 3 "register_operand"))))
>       (clobber (match_dup4))])]
> "TARGET_VECTOR"
>    {
> operands[4] = gen_reg_rtx (Pmode);
> })
> 
> (define_insn_and_split "*fms<VF_AUTO:mode><P:mode>"
>    [(set (match_operand:VF_AUTO 0 "register_operand" "=vr, vr, ?&vr")
>    (fma:VF_AUTO
>      (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
>      (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
>      (neg:VF_AUTO
>        (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr"))))
>     (clobber (match_operand:P 4 "=r,r,r"))]
> "TARGET_VECTOR"
> "#"
> "&& reload_completed"
>    [(const_int 0)]
>    {
>      riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
>      if (which_alternative == 2)
>        emit_insn (gen_rtx_SET (operands[0], operands[3]));
>      rtx ops[] = {operands[0], operands[1], operands[2], operands[3], 
> operands[0]};
>      riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (MINUS, 
> <MODE>mode),
>                  riscv_vector::RVV_TERNOP, ops, operands[4]);
>      DONE;
>    }
>    [(set_attr "type" "vfmuladd")
>     (set_attr "mode" "<MODE>")])
> 
> It fails and create ICE.
But where did ICE and *why*?  That's really the question.  Changing the 
mode just looks like papering over a more serious issue.
 
jeff
diff mbox series

Patch

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index f1641d7e1ea..ddee6171acb 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -676,6 +676,186 @@ 
   [(set_attr "type" "vimuladd")
    (set_attr "mode" "<MODE>")])
 
+;; -------------------------------------------------------------------------
+;; ---- [FP] VFMACC and VFMADD
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfmacc
+;; - vfmadd
+;; -------------------------------------------------------------------------
+
+(define_expand "fma<mode>4"
+  [(parallel
+    [(set (match_operand:VF_AUTO 0 "register_operand")
+	  (fma:VF_AUTO
+	    (match_operand:VF_AUTO 1 "register_operand")
+	    (match_operand:VF_AUTO 2 "register_operand")
+	    (match_operand:VF_AUTO 3 "register_operand")))
+     (clobber (match_scratch:SI 4))])]
+  "TARGET_VECTOR"
+  {})
+
+(define_insn_and_split "*fma<mode>"
+  [(set (match_operand:VF_AUTO 0 "register_operand"   "=vr, vr, ?&vr")
+	(fma:VF_AUTO
+	  (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr")
+	  (match_operand:VF_AUTO 2 "register_operand" " vr, vr,   vr")
+	  (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr")))
+   (clobber (match_scratch:SI 4 "=r,r,r"))]
+  "TARGET_VECTOR"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    PUT_MODE (operands[4], Pmode);
+    riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
+    if (which_alternative == 2)
+      emit_insn (gen_rtx_SET (operands[0], operands[3]));
+    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
+    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (PLUS, <MODE>mode),
+					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    DONE;
+  }
+  [(set_attr "type" "vfmuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] VFNMSAC and VFNMSUB
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfnmsac
+;; - vfnmsub
+;; -------------------------------------------------------------------------
+
+(define_expand "fnma<mode>4"
+  [(parallel
+    [(set (match_operand:VF_AUTO 0 "register_operand")
+	  (fma:VF_AUTO
+	    (neg:VF_AUTO
+	      (match_operand:VF_AUTO 1 "register_operand"))
+	    (match_operand:VF_AUTO 2 "register_operand")
+	    (match_operand:VF_AUTO 3 "register_operand")))
+     (clobber (match_scratch:SI 4))])]
+  "TARGET_VECTOR"
+  {})
+
+(define_insn_and_split "*fnma<mode>"
+  [(set (match_operand:VF_AUTO 0 "register_operand"     "=vr, vr, ?&vr")
+	(fma:VF_AUTO
+	  (neg:VF_AUTO
+	    (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr"))
+	  (match_operand:VF_AUTO 2 "register_operand"   " vr, vr,   vr")
+	  (match_operand:VF_AUTO 3 "register_operand"   " vr,  0,   vr")))
+   (clobber (match_scratch:SI 4 "=r,r,r"))]
+  "TARGET_VECTOR"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    PUT_MODE (operands[4], Pmode);
+    riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
+    if (which_alternative == 2)
+      emit_insn (gen_rtx_SET (operands[0], operands[3]));
+    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
+    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul_neg (PLUS, <MODE>mode),
+					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    DONE;
+  }
+  [(set_attr "type" "vfmuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] VFMSAC and VFMSUB
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfmsac
+;; - vfmsub
+;; -------------------------------------------------------------------------
+
+(define_expand "fms<mode>4"
+  [(parallel
+    [(set (match_operand:VF_AUTO 0 "register_operand")
+	  (fma:VF_AUTO
+	    (match_operand:VF_AUTO 1 "register_operand")
+	    (match_operand:VF_AUTO 2 "register_operand")
+	    (neg:VF_AUTO
+	      (match_operand:VF_AUTO 3 "register_operand"))))
+     (clobber (match_scratch:SI 4))])]
+  "TARGET_VECTOR"
+  {})
+
+(define_insn_and_split "*fms<mode>"
+  [(set (match_operand:VF_AUTO 0 "register_operand"     "=vr, vr, ?&vr")
+	(fma:VF_AUTO
+	  (match_operand:VF_AUTO 1 "register_operand"   " %0, vr,   vr")
+	  (match_operand:VF_AUTO 2 "register_operand"   " vr, vr,   vr")
+	  (neg:VF_AUTO
+	    (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr"))))
+   (clobber (match_scratch:SI 4 "=r,r,r"))]
+  "TARGET_VECTOR"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    PUT_MODE (operands[4], Pmode);
+    riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
+    if (which_alternative == 2)
+      emit_insn (gen_rtx_SET (operands[0], operands[3]));
+    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
+    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (MINUS, <MODE>mode),
+					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    DONE;
+  }
+  [(set_attr "type" "vfmuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] VFMSAC and VFMSUB
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfmsac
+;; - vfmsub
+;; -------------------------------------------------------------------------
+
+(define_expand "fnms<mode>4"
+  [(parallel
+    [(set (match_operand:VF_AUTO 0 "register_operand")
+	  (fma:VF_AUTO
+	    (neg:VF_AUTO
+	      (match_operand:VF_AUTO 1 "register_operand"))
+	    (match_operand:VF_AUTO 2 "register_operand")
+	    (neg:VF_AUTO
+	      (match_operand:VF_AUTO 3 "register_operand"))))
+     (clobber (match_scratch:SI 4))])]
+  "TARGET_VECTOR"
+  {})
+
+(define_insn_and_split "*fnms<mode>"
+  [(set (match_operand:VF_AUTO 0 "register_operand"     "=vr, vr, ?&vr")
+	(fma:VF_AUTO
+	  (neg:VF_AUTO
+	    (match_operand:VF_AUTO 1 "register_operand" " %0, vr,   vr"))
+	  (match_operand:VF_AUTO 2 "register_operand"   " vr, vr,   vr")
+	  (neg:VF_AUTO
+	    (match_operand:VF_AUTO 3 "register_operand" " vr,  0,   vr"))))
+   (clobber (match_scratch:SI 4 "=r,r,r"))]
+  "TARGET_VECTOR"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    PUT_MODE (operands[4], Pmode);
+    riscv_vector::emit_vlmax_vsetvl (<MODE>mode, operands[4]);
+    if (which_alternative == 2)
+      emit_insn (gen_rtx_SET (operands[0], operands[3]));
+    rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
+    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul_neg (MINUS, <MODE>mode),
+					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    DONE;
+  }
+  [(set_attr "type" "vfmuladd")
+   (set_attr "mode" "<MODE>")])
+
 ;; =========================================================================
 ;; == SELECT_VL
 ;; =========================================================================
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f052757cede..6d607dc61d1 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -187,6 +187,7 @@  void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_insn (unsigned, int, rtx *, rtx = 0);
 void emit_vlmax_fp_insn (unsigned, int, rtx *, rtx = 0);
 void emit_vlmax_ternary_insn (unsigned, int, rtx *, rtx = 0);
+void emit_vlmax_fp_ternary_insn (unsigned, int, rtx *, rtx = 0);
 void emit_nonvlmax_insn (unsigned, int, rtx *, rtx);
 void emit_vlmax_slide_insn (unsigned, rtx *);
 void emit_nonvlmax_slide_tu_insn (unsigned, rtx *, rtx);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 839a2c6ba71..87c537b9e61 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -718,6 +718,27 @@  emit_vlmax_ternary_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
   e.emit_insn ((enum insn_code) icode, ops);
 }
 
+/* This function emits a {VLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
+ * ternary operation which always has a real merge operand.  */
+void
+emit_vlmax_fp_ternary_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
+{
+  machine_mode dest_mode = GET_MODE (ops[0]);
+  machine_mode mask_mode = get_mask_mode (dest_mode).require ();
+  /* We have a maximum of 11 operands for RVV instruction patterns according to
+   * vector.md.  */
+  insn_expander<11> e (/*OP_NUM*/ op_num, /*HAS_DEST_P*/ true,
+		       /*FULLY_UNMASKED_P*/ true,
+		       /*USE_REAL_MERGE_P*/ true, /*HAS_AVL_P*/ true,
+		       /*VLMAX_P*/ true,
+		       /*DEST_MODE*/ dest_mode, /*MASK_MODE*/ mask_mode);
+  e.set_policy (TAIL_ANY);
+  e.set_policy (MASK_ANY);
+  e.set_rounding_mode (FRM_DYN);
+  e.set_vl (vl);
+  e.emit_insn ((enum insn_code) icode, ops);
+}
+
 /* This function emits a {NONVLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
  * actual operation.  */
 void
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 884e7435cc2..858abdc684c 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -425,14 +425,14 @@ 
 	 (eq_attr "type" "vldux,vldox,vialu,vshift,viminmax,vimul,vidiv,vsalu,\
 			  viwalu,viwmul,vnshift,vaalu,vsmul,vsshift,\
 			  vnclip,vicmp,vfalu,vfmul,vfminmax,vfdiv,vfwalu,vfwmul,\
-			  vfsgnj,vfcmp,vfmuladd,vslideup,vslidedown,vislide1up,\
+			  vfsgnj,vfcmp,vslideup,vslidedown,vislide1up,\
 			  vislide1down,vfslide1up,vfslide1down,vgather,viwmuladd,vfwmuladd,\
 			  vlsegds,vlsegdux,vlsegdox")
 	   (symbol_ref "INTVAL (operands[8])")
 	 (eq_attr "type" "vstux,vstox,vssegts,vssegtux,vssegtox")
 	   (symbol_ref "INTVAL (operands[5])")
 
-	 (eq_attr "type" "vimuladd")
+	 (eq_attr "type" "vimuladd,vfmuladd")
 	   (symbol_ref "INTVAL (operands[9])")
 
 	 (eq_attr "type" "vmsfs,vmidx,vcompress")
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-1.c
index 1996ca65108..442000117b1 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -20,9 +20,13 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
 /* { dg-final { scan-assembler-times {\tvmadd\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmadd\.vv} 3 } } */
 /* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-10.c
new file mode 100644
index 00000000000..fc66def0577
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-10.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dst,            \
+					      TYPE *__restrict a,              \
+					      TYPE *__restrict b, int n)       \
+  {                                                                            \
+    for (int i = 0; i < n; i++)                                                \
+      dst[i] = -(a[i] * b[i]) - dst[i];                                        \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvfnmadd\.vv} 3 } } */
+/* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-11.c
new file mode 100644
index 00000000000..23c542f9f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-11.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dest1,          \
+					      TYPE *__restrict dest2,          \
+					      TYPE *__restrict dest3,          \
+					      TYPE *__restrict src1,           \
+					      TYPE *__restrict src2, int n)    \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      {                                                                        \
+	dest1[i] = -(src1[i] * src2[i]) - dest1[i];                            \
+	dest2[i] = src1[i] * dest1[i] - dest2[i];                              \
+	dest3[i] = src2[i] * dest2[i] - dest3[i];                              \
+      }                                                                        \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvfnmacc\.vv} 3 } } */
+/* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-12.c
new file mode 100644
index 00000000000..8ec261b799a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-12.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dest1,          \
+					      TYPE *__restrict dest2,          \
+					      TYPE *__restrict dest3,          \
+					      TYPE *__restrict src1,           \
+					      TYPE *__restrict src2, int n)    \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      {                                                                        \
+	dest1[i] = -(src1[i] * src2[i]) - dest2[i];                            \
+	dest2[i] = src1[i] * dest1[i] - dest2[i];                              \
+	dest3[i] = src2[i] * dest2[i] - dest3[i];                              \
+      }                                                                        \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvmv} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-2.c
index e52e07ddd09..ad2673a05bc 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -26,9 +26,13 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
 /* { dg-final { scan-assembler-times {\tvmacc\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmacc\.vv} 3 } } */
 /* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-3.c
index 127e701b187..cd97f4d980e 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -26,8 +26,11 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
-/* { dg-final { scan-assembler-times {\tvmv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvmv} 11 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-4.c
index 1b8b934149e..a225ea0757b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-4.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -20,9 +20,13 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
 /* { dg-final { scan-assembler-times {\tvnmsub\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfnmsub\.vv} 3 } } */
 /* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-5.c
index 49c85efbf3a..12dfa0ac21d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-5.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -26,9 +26,13 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
 /* { dg-final { scan-assembler-times {\tvnmsac\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfnmsac\.vv} 3 } } */
 /* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-6.c
index f38f303574f..b83590f1a46 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-6.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include <stdint-gcc.h>
 
@@ -26,8 +26,11 @@ 
   TEST_TYPE (int32_t)                                                          \
   TEST_TYPE (uint32_t)                                                         \
   TEST_TYPE (int64_t)                                                          \
-  TEST_TYPE (uint64_t)
+  TEST_TYPE (uint64_t)                                                         \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
 
 TEST_ALL ()
 
-/* { dg-final { scan-assembler-times {\tvmv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvmv} 11 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-7.c
new file mode 100644
index 00000000000..0f80da4a69d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-7.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dst,            \
+					      TYPE *__restrict a,              \
+					      TYPE *__restrict b, int n)       \
+  {                                                                            \
+    for (int i = 0; i < n; i++)                                                \
+      dst[i] = a[i] * b[i] - dst[i];                                           \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvfmsub\.vv} 3 } } */
+/* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-8.c
new file mode 100644
index 00000000000..ae65298f06a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-8.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -fno-schedule-insns -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dest1,          \
+					      TYPE *__restrict dest2,          \
+					      TYPE *__restrict dest3,          \
+					      TYPE *__restrict src1,           \
+					      TYPE *__restrict src2, int n)    \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      {                                                                        \
+	dest1[i] = src1[i] * src2[i] - dest1[i];                               \
+	dest2[i] = src1[i] * dest1[i] - dest2[i];                              \
+	dest3[i] = src2[i] * dest2[i] - dest3[i];                              \
+      }                                                                        \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvfmsac\.vv} 3 } } */
+/* { dg-final { scan-assembler-not {\tvmv} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-9.c
new file mode 100644
index 00000000000..299bd2dbcec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop-9.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE)                                                        \
+  __attribute__ ((noipa)) void ternop_##TYPE (TYPE *__restrict dest1,          \
+					      TYPE *__restrict dest2,          \
+					      TYPE *__restrict dest3,          \
+					      TYPE *__restrict src1,           \
+					      TYPE *__restrict src2, int n)    \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      {                                                                        \
+	dest1[i] = src1[i] * src2[i] - dest2[i];                               \
+	dest2[i] = src1[i] * dest1[i] - dest2[i];                              \
+	dest3[i] = src2[i] * dest2[i] - dest3[i];                              \
+      }                                                                        \
+  }
+
+#define TEST_ALL()                                                             \
+  TEST_TYPE (_Float16)                                                         \
+  TEST_TYPE (float)                                                            \
+  TEST_TYPE (double)
+
+TEST_ALL ()
+
+/* { dg-final { scan-assembler-times {\tvmv} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c
index 1f69b694818..e0ec9ed48dd 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-1.c"
 
@@ -80,5 +80,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c
new file mode 100644
index 00000000000..854827fd465
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-10.c
@@ -0,0 +1,40 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-10.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+   != (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array4_##NUM[i]))  \
+ __builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c
new file mode 100644
index 00000000000..b5a0845026b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-11.c
@@ -0,0 +1,60 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-11.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array6_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c
new file mode 100644
index 00000000000..c7c4b4b50f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-12.c
@@ -0,0 +1,60 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-12.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array7_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c
index 103b98acdf0..ee7c7251698 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-2.c"
 
@@ -100,5 +100,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c
index eac5408ce6f..6c4f28e8c02 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-3.c"
 
@@ -100,5 +100,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c
index c6f1fe591f3..44a4771cb84 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-4.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-4.c"
 
@@ -80,5 +80,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c
index 81af4b672a5..efe2f362189 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-5.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-5.c"
 
@@ -100,5 +100,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c
index b5e579ef55a..f1ce6a756ac 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-6.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "--param=riscv-autovec-preference=scalable" } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
 
 #include "ternop-6.c"
 
@@ -100,5 +100,15 @@  int __attribute__ ((optimize (0))) main ()
   TEST_LOOP (int64_t, 795)
   TEST_LOOP (uint64_t, 795)
 
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c
new file mode 100644
index 00000000000..1809b237467
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-7.c
@@ -0,0 +1,40 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-7.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+	  != (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array4_##NUM[i]))     \
+	__builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c
new file mode 100644
index 00000000000..f048652f433
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-8.c
@@ -0,0 +1,60 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-8.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array6_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c
new file mode 100644
index 00000000000..dcf87f67452
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run-9.c
@@ -0,0 +1,60 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-9.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array7_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (float, 7)
+  TEST_LOOP (double, 7)
+  TEST_LOOP (float, 16)
+  TEST_LOOP (double, 16)
+  TEST_LOOP (float, 77)
+  TEST_LOOP (double, 77)
+  TEST_LOOP (float, 128)
+  TEST_LOOP (double, 128)
+  TEST_LOOP (float, 795)
+  TEST_LOOP (double, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c
new file mode 100644
index 00000000000..84fcb683341
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-1.c
@@ -0,0 +1,35 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-1.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+	  != (TYPE) (array1_##NUM[i] * array2_##NUM[i] + array4_##NUM[i]))     \
+	__builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c
new file mode 100644
index 00000000000..d669cd4f2c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-10.c
@@ -0,0 +1,35 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-10.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+   != (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array4_##NUM[i]))  \
+ __builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c
new file mode 100644
index 00000000000..fac17b62c59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-11.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-11.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array6_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c
new file mode 100644
index 00000000000..a51b926d036
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-12.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-12.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) - array7_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c
new file mode 100644
index 00000000000..8fc6a1b33d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-2.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-2.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] + array6_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] + array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] + array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c
new file mode 100644
index 00000000000..36013072415
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-3.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-3.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] + array7_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] + array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] + array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c
new file mode 100644
index 00000000000..a26bcaa6017
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-4.c
@@ -0,0 +1,35 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-4.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+   != (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) + array4_##NUM[i]))  \
+ __builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c
new file mode 100644
index 00000000000..6dee6ba7c99
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-5.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-5.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) + array6_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] + array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] + array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c
new file mode 100644
index 00000000000..3fdf2d30df9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-6.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-6.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+ array1_##NUM[i] = (i & 1) + 5;                                         \
+ array2_##NUM[i] = i - NUM / 3;                                         \
+ array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+ array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+ array5_##NUM[i] = NUM + i * 7;                                         \
+ array8_##NUM[i] = NUM + i * 7;                                         \
+ asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+    array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+ array6_##NUM[i]                                                        \
+   = (TYPE) (-(array1_##NUM[i] * array2_##NUM[i]) + array7_##NUM[i]);   \
+ if (array3_##NUM[i] != array6_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array7_##NUM[i]                                                        \
+   = (TYPE) (array1_##NUM[i] * array6_##NUM[i] + array7_##NUM[i]);      \
+ if (array4_##NUM[i] != array7_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+ array8_##NUM[i]                                                        \
+   = (TYPE) (array2_##NUM[i] * array7_##NUM[i] + array8_##NUM[i]);      \
+ if (array5_##NUM[i] != array8_##NUM[i])                                \
+   __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c
new file mode 100644
index 00000000000..a25a6f7f188
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-7.c
@@ -0,0 +1,35 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-7.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array1_##NUM, array2_##NUM, NUM);             \
+    for (int i = 0; i < NUM; i++)                                              \
+      if (array3_##NUM[i]                                                      \
+	  != (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array4_##NUM[i]))     \
+	__builtin_abort ();                                                    \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c
new file mode 100644
index 00000000000..1d90bee1623
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-8.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-8.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array6_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c
new file mode 100644
index 00000000000..c633f545349
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/ternop/ternop_run_zvfh-9.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math" } */
+
+#include "ternop-9.c"
+
+#define TEST_LOOP(TYPE, NUM)                                                   \
+  {                                                                            \
+    TYPE array1_##NUM[NUM] = {};                                               \
+    TYPE array2_##NUM[NUM] = {};                                               \
+    TYPE array3_##NUM[NUM] = {};                                               \
+    TYPE array4_##NUM[NUM] = {};                                               \
+    TYPE array5_##NUM[NUM] = {};                                               \
+    TYPE array6_##NUM[NUM] = {};                                               \
+    TYPE array7_##NUM[NUM] = {};                                               \
+    TYPE array8_##NUM[NUM] = {};                                               \
+    for (int i = 0; i < NUM; ++i)                                              \
+      {                                                                        \
+	array1_##NUM[i] = (i & 1) + 5;                                         \
+	array2_##NUM[i] = i - NUM / 3;                                         \
+	array3_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array6_##NUM[i] = NUM - NUM / 3 - i;                                   \
+	array4_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array7_##NUM[i] = NUM - NUM / 2 + i;                                   \
+	array5_##NUM[i] = NUM + i * 7;                                         \
+	array8_##NUM[i] = NUM + i * 7;                                         \
+	asm volatile("" ::: "memory");                                         \
+      }                                                                        \
+    ternop_##TYPE (array3_##NUM, array4_##NUM, array5_##NUM, array1_##NUM,     \
+		   array2_##NUM, NUM);                                         \
+    for (int i = 0; i < NUM; i++)                                              \
+      {                                                                        \
+	array6_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array2_##NUM[i] - array7_##NUM[i]);      \
+	if (array3_##NUM[i] != array6_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array7_##NUM[i]                                                        \
+	  = (TYPE) (array1_##NUM[i] * array6_##NUM[i] - array7_##NUM[i]);      \
+	if (array4_##NUM[i] != array7_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+	array8_##NUM[i]                                                        \
+	  = (TYPE) (array2_##NUM[i] * array7_##NUM[i] - array8_##NUM[i]);      \
+	if (array5_##NUM[i] != array8_##NUM[i])                                \
+	  __builtin_abort ();                                                  \
+      }                                                                        \
+  }
+
+int __attribute__ ((optimize (0))) main ()
+{
+  TEST_LOOP (_Float16, 7)
+  TEST_LOOP (_Float16, 16)
+  TEST_LOOP (_Float16, 77)
+  TEST_LOOP (_Float16, 128)
+  TEST_LOOP (_Float16, 795)
+  return 0;
+}