[v3] RISC-V: Add autovec FP binary operations.

Message ID b4438c7c-4aca-23a6-5482-464bc5eb0f14@gmail.com
State Unresolved
Headers
Series [v3] RISC-V: Add autovec FP binary operations. |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Robin Dapp June 16, 2023, 1:29 p.m. UTC
  Hi,

changes in v3:
 - No longer "dependent" on testsuite changes.  Just the zvfh
run testcases use riscv_zvfh_hw, i.e. require that we can compile,
link the code as well as execute the resulting binary.  
 - Renamed rounding modes (floating_point_rounding_mode feels a
bit long-winded but well...)

Regards
 Robin


This implements the floating-point autovec expanders for binary
operations: vfadd, vfsub, vfdiv, vfmul, vfmax, vfmin and adds
tests.

The existing tests are split up into non-_Float16 and _Float16
flavors as we cannot rely on the zvfh extension being present.

As long as we do not have full middle-end support we need
-ffast-math for the tests.

In order to allow proper _Float16 support we need to disable
promotion to float.  This patch handles that similarly to
TARGET_ZFH and TARGET_ZINX.  This is not strictly accurate
as the zvfh extension only requires the zfhmin i.e. just
conversion to float and no actual operations.

gcc/ChangeLog:

	* config/riscv/autovec.md (<optab><mode>3): Implement binop
	expander.
	* config/riscv/riscv-protos.h (emit_vlmax_fp_insn): Declare.
	(emit_vlmax_fp_minmax_insn): Declare.
	(enum frm_field_enum): Rename this...
	(enum rounding_mode): ...to this.
	* config/riscv/riscv-v.cc (emit_vlmax_fp_insn): New function
	(emit_vlmax_fp_minmax_insn): New function.
	* config/riscv/riscv.cc (riscv_const_insns): Clarify const
	vector handling.
	(riscv_libgcc_floating_mode_supported_p): Adjust comment.
	(riscv_excess_precision): Do not convert to float for ZVFH.
	* config/riscv/vector-iterators.md: Add VF_AUTO iterator.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/binop/vadd-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vadd-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vadd-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vadd-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vdiv-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vdiv-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmax-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmax-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmax-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmax-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmin-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmin-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmin-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmin-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmul-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmul-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmul-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vmul-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vrem-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vsub-run.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vsub-rv32gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vsub-rv64gcv.c: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vsub-template.h: Add FP.
	* gcc.target/riscv/rvv/autovec/binop/vadd-zvfh-run.c: New test.
	* gcc.target/riscv/rvv/autovec/binop/vdiv-zvfh-run.c: New test.
	* gcc.target/riscv/rvv/autovec/binop/vmax-zvfh-run.c: New test.
	* gcc.target/riscv/rvv/autovec/binop/vmin-zvfh-run.c: New test.
	* gcc.target/riscv/rvv/autovec/binop/vmul-zvfh-run.c: New test.
	* gcc.target/riscv/rvv/autovec/binop/vsub-zvfh-run.c: New test.
	* lib/target-supports.exp: Add riscv_vector_hw and riscv_zvfh_hw
	target selectors.
---
 gcc/config/riscv/autovec.md                   | 36 +++++++++
 gcc/config/riscv/riscv-protos.h               |  8 +-
 gcc/config/riscv/riscv-v.cc                   | 74 ++++++++++++++++++-
 gcc/config/riscv/riscv.cc                     | 27 +++++--
 gcc/config/riscv/vector-iterators.md          | 28 +++++++
 .../riscv/rvv/autovec/binop/vadd-run.c        | 12 ++-
 .../riscv/rvv/autovec/binop/vadd-rv32gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vadd-rv64gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vadd-template.h   | 11 ++-
 .../riscv/rvv/autovec/binop/vadd-zvfh-run.c   | 54 ++++++++++++++
 .../riscv/rvv/autovec/binop/vdiv-run.c        |  8 +-
 .../riscv/rvv/autovec/binop/vdiv-rv32gcv.c    |  7 +-
 .../riscv/rvv/autovec/binop/vdiv-rv64gcv.c    |  7 +-
 .../riscv/rvv/autovec/binop/vdiv-template.h   |  8 +-
 .../riscv/rvv/autovec/binop/vdiv-zvfh-run.c   | 37 ++++++++++
 .../riscv/rvv/autovec/binop/vmax-run.c        |  9 ++-
 .../riscv/rvv/autovec/binop/vmax-rv32gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vmax-rv64gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vmax-template.h   |  8 +-
 .../riscv/rvv/autovec/binop/vmax-zvfh-run.c   | 38 ++++++++++
 .../riscv/rvv/autovec/binop/vmin-run.c        | 10 ++-
 .../riscv/rvv/autovec/binop/vmin-rv32gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vmin-rv64gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vmin-template.h   |  8 +-
 .../riscv/rvv/autovec/binop/vmin-zvfh-run.c   | 37 ++++++++++
 .../riscv/rvv/autovec/binop/vmul-run.c        |  8 +-
 .../riscv/rvv/autovec/binop/vmul-rv32gcv.c    |  2 +-
 .../riscv/rvv/autovec/binop/vmul-rv64gcv.c    |  2 +-
 .../riscv/rvv/autovec/binop/vmul-template.h   |  8 +-
 .../riscv/rvv/autovec/binop/vmul-zvfh-run.c   | 37 ++++++++++
 .../riscv/rvv/autovec/binop/vrem-rv32gcv.c    |  3 +-
 .../riscv/rvv/autovec/binop/vsub-run.c        | 12 ++-
 .../riscv/rvv/autovec/binop/vsub-rv32gcv.c    |  8 +-
 .../riscv/rvv/autovec/binop/vsub-rv64gcv.c    |  8 +-
 .../riscv/rvv/autovec/binop/vsub-template.h   | 16 +++-
 .../riscv/rvv/autovec/binop/vsub-zvfh-run.c   | 55 ++++++++++++++
 gcc/testsuite/lib/target-supports.exp         | 49 ++++++++++++
 37 files changed, 604 insertions(+), 49 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-zvfh-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-zvfh-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-zvfh-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-zvfh-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-zvfh-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-zvfh-run.c
  

Comments

Lehua Ding Sept. 6, 2023, 9:43 a.m. UTC | #1
Hi Robin,

> +# Return 1 if the we can build a vector example with proper -march flags
> +# and the current target can execute it, 0 otherwise.  Cache the result.
> +
> +proc check_effective_target_riscv_vector_hw { } {
> +
> +    return [check_runtime riscv_vector_hw32 {
> +        int main (void)
> +        {
> +            asm ("vsetivli zero,8,e16,m1,ta,ma");
> +            asm ("vadd.vv v8,v8,v16" : : : "v8");
> +            return 0;
> +        }
> +    } "-march=rv32gcv -mabi=ilp32d"] || [check_runtime riscv_vector_hw64 {
> +        int main (void)
> +        {
> +            asm ("vsetivli zero,8,e16,m1,ta,ma");
> +            asm ("vadd.vv v8,v8,v16" : : : "v8");
> +            return 0;
> +        }
> +    } "-march=rv64gcv -mabi=lp64d"]
> +}
> +
> +# Return 1 if the we can build a Zvfh vector example with proper -march flags
> +# and the current target can execute it, 0 otherwise.  Cache the result.
> +
> +proc check_effective_target_riscv_zvfh_hw { } {
> +    if ![check_effective_target_riscv_vector_hw] then {
> +        return 0
> +    }
> +
> +    return [check_runtime riscv_zvfh_hw32 {
> +        int main (void)
> +        {
> +            asm ("vsetivli zero,8,e16,m1,ta,ma");
> +            asm ("vfadd.vv v8,v8,v16" : : : "v8");
> +            return 0;
> +        }
> +    } "-march=rv32gcv_zvfh -mabi=ilp32d"]
> +    || [check_runtime riscv_zvfh_hw64 {
> +        int main (void)
> +        {
> +            asm ("vsetivli zero,8,e16,m1,ta,ma");
> +            asm ("vfadd.vv v8,v8,v16" : : : "v8");
> +            return 0;
> +        }
> +    } "-march=rv64gcv_zvfh -mabi=lp64d"]

May I ask if the compiler options "-march=rv64gcv_zvfh -mabi=lp64d" 
should be removed? Because we don't specify -march and -mabi when we run 
testcase (so but why we need to specify the -march and -mabi in this 
target check?), we run it with the default values. Assuming that the 
default is rv64gcv_zvfh_zfh, `riscv_vector` check will fail because 
compile and link with -march=rv64gcv will throw the following error if I 
doesn't compile a multilibs compilers. But in fact rv64gcv_zvfh_zfh 
contains rv64gcv, we should not let this case report link error.:

riscv64-unknown-elf-gcc: fatal error: Cannot find suitable multilib set 
for 
'-march=rv64imafdcv_zicsr_zifencei_zve32f_zve32x_zve64d_zve64f_zve64x_zvl128b_zvl32b_zvl64b'/'-mabi=lp64d'

I think we should use the default march and mabi to check whether we can 
compile and execute specified instructions.
  
Robin Dapp Sept. 6, 2023, 1:27 p.m. UTC | #2
Hi Lehua,

> May I ask if the compiler options "-march=rv64gcv_zvfh -mabi=lp64d"
> should be removed? Because we don't specify -march and -mabi when we
> run testcase (so but why we need to specify the -march and -mabi in
> this target check?), we run it with the default values. Assuming that
> the default is rv64gcv_zvfh_zfh, `riscv_vector` check will fail
> because compile and link with -march=rv64gcv will throw the following
> error if I doesn't compile a multilibs compilers. But in fact
> rv64gcv_zvfh_zfh contains rv64gcv, we should not let this case report
> link error.:

Yes, you're right, this should not be necessary.  This is more of a
test for the execution environment than the compiler.  I think Juzhe
removed it already in his patch that enables the vector test suite.
In the future we would use the checks that Joern added, not sure if
they are already upstream.

Regards
 Robin
  
Lehua Ding Sept. 7, 2023, 3:25 a.m. UTC | #3
Hi Robin,

> Yes, you're right, this should not be necessary.  This is more of a
> test for the execution environment than the compiler.  I think Juzhe
> removed it already in his patch that enables the vector test suite.
> In the future we would use the checks that Joern added, not sure if
> they are already upstream
All right, let's wait for further action. Thanks.
  

Patch

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 579cbb07234..94452c932a4 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -769,3 +769,39 @@  (define_expand "vec_init<vi_half><mode>"
 {
   DONE;
 })
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Binary operations
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfadd.vv/vfsub.vv/...
+;; - vfadd.vf/vfsub.vf/...
+;; -------------------------------------------------------------------------
+(define_expand "<optab><mode>3"
+  [(match_operand:VF_AUTO 0 "register_operand")
+   (any_float_binop:VF_AUTO
+    (match_operand:VF_AUTO 1 "register_operand")
+    (match_operand:VF_AUTO 2 "register_operand"))]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_vlmax_fp_insn (code_for_pred (<CODE>, <MODE>mode),
+				    riscv_vector::RVV_BINOP, operands);
+  DONE;
+})
+
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vfmin.vv/vfmax.vv
+;; - vfmin.vf/vfmax.vf
+;; -------------------------------------------------------------------------
+(define_expand "<optab><mode>3"
+  [(match_operand:VF_AUTO 0 "register_operand")
+   (any_float_binop_nofrm:VF_AUTO
+    (match_operand:VF_AUTO 1 "register_operand")
+    (match_operand:VF_AUTO 2 "register_operand"))]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_vlmax_fp_minmax_insn (code_for_pred (<CODE>, <MODE>mode),
+					   riscv_vector::RVV_BINOP, operands);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f422adf8521..d0db1343b15 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -185,6 +185,8 @@  bool legitimize_move (rtx, rtx);
 void emit_vlmax_vsetvl (machine_mode, rtx);
 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_fp_minmax_insn (unsigned, int, rtx *, rtx = 0);
 void emit_vlmax_ternary_insn (unsigned, int, rtx *, rtx = 0);
 void emit_nonvlmax_insn (unsigned, int, rtx *, rtx);
 void emit_vlmax_slide_insn (unsigned, rtx *);
@@ -252,19 +254,21 @@  void expand_vec_init (rtx, rtx);
 void expand_vcond (rtx *);
 void expand_vec_perm (rtx, rtx, rtx, rtx);
 void expand_select_vl (rtx *);
+
 /* Rounding mode bitfield for fixed point VXRM.  */
-enum vxrm_field_enum
+enum fixed_point_rounding_mode
 {
   VXRM_RNU,
   VXRM_RNE,
   VXRM_RDN,
   VXRM_ROD
 };
+
 /* Rounding mode bitfield for floating point FRM.  The value of enum comes
    from the below link.
    https://github.com/riscv/riscv-isa-manual/blob/main/src/f-st-ext.adoc#floating-point-control-and-status-register
  */
-enum frm_field_enum
+enum floating_point_rounding_mode
 {
   FRM_RNE = 0, /* Aka 0b000.  */
   FRM_RTZ = 1, /* Aka 0b001.  */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 1c86cfbdcee..207ea273f41 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -74,8 +74,10 @@  public:
     : m_opno (0), m_op_num (0), m_has_dest_p (false),
       m_fully_unmasked_p (false), m_use_real_merge_p (false),
       m_needs_avl_p (false), m_vlmax_p (false), m_has_tail_policy_p (false),
-      m_has_mask_policy_p (false), m_tail_policy (TAIL_ANY),
-      m_mask_policy (MASK_ANY), m_dest_mode (VOIDmode), m_mask_mode (VOIDmode),
+      m_has_mask_policy_p (false), m_has_fp_rounding_mode_p (false),
+      m_tail_policy (TAIL_ANY), m_mask_policy (MASK_ANY),
+      m_fp_rounding_mode (FRM_DYN),
+      m_dest_mode (VOIDmode), m_mask_mode (VOIDmode),
       m_vl_op (NULL_RTX)
   {}
 
@@ -87,8 +89,10 @@  public:
       m_fully_unmasked_p (use_all_trues_mask_p),
       m_use_real_merge_p (use_real_merge_p), m_needs_avl_p (needs_avl_p),
       m_vlmax_p (vlmax_p), m_has_tail_policy_p (false),
-      m_has_mask_policy_p (false), m_tail_policy (TAIL_ANY),
-      m_mask_policy (MASK_ANY), m_dest_mode (dest_mode),
+      m_has_mask_policy_p (false), m_has_fp_rounding_mode_p (false),
+      m_tail_policy (TAIL_ANY), m_mask_policy (MASK_ANY),
+      m_fp_rounding_mode (FRM_DYN),
+      m_dest_mode (dest_mode),
       m_mask_mode (mask_mode), m_vl_op (NULL_RTX)
   {}
 
@@ -104,6 +108,12 @@  public:
   }
   void set_vl (rtx vl) { m_vl_op = vl; }
 
+  void set_rounding_mode (enum floating_point_rounding_mode mode)
+  {
+    m_has_fp_rounding_mode_p = true;
+    m_fp_rounding_mode = mode;
+  }
+
   void add_output_operand (rtx x, machine_mode mode)
   {
     create_output_operand (&m_ops[m_opno++], x, mode);
@@ -140,6 +150,15 @@  public:
     add_input_operand (gen_int_mode (type, Pmode), Pmode);
   }
 
+  void add_rounding_mode_operand ()
+  {
+    if (m_has_fp_rounding_mode_p)
+      {
+	rtx frm_rtx = gen_int_mode (m_fp_rounding_mode, Pmode);
+	add_input_operand (frm_rtx, Pmode);
+      }
+  }
+
   void emit_insn (enum insn_code icode, rtx *ops)
   {
     int opno = 0;
@@ -200,6 +219,9 @@  public:
       add_policy_operand ();
     if (m_needs_avl_p)
       add_avl_type_operand (m_vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
+
+    add_rounding_mode_operand ();
+
     expand (icode, any_mem_p);
   }
 
@@ -231,8 +253,10 @@  private:
   bool m_vlmax_p;
   bool m_has_tail_policy_p;
   bool m_has_mask_policy_p;
+  bool m_has_fp_rounding_mode_p;
   enum tail_policy m_tail_policy;
   enum mask_policy m_mask_policy;
+  enum floating_point_rounding_mode m_fp_rounding_mode;
   machine_mode m_dest_mode;
   machine_mode m_mask_mode;
   rtx m_vl_op;
@@ -653,6 +677,48 @@  emit_vlmax_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
   e.emit_insn ((enum insn_code) icode, ops);
 }
 
+void
+emit_vlmax_fp_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 ();
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
+					  /* HAS_DEST_P */ true,
+					  /* FULLY_UNMASKED_P */ true,
+					  /* USE_REAL_MERGE_P */ false,
+					  /* HAS_AVL_P */ true,
+					  /* VLMAX_P */ true,
+					  dest_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);
+}
+
+void
+emit_vlmax_fp_minmax_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 ();
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
+					  /* HAS_DEST_P */ true,
+					  /* FULLY_UNMASKED_P */ true,
+					  /* USE_REAL_MERGE_P */ false,
+					  /* HAS_AVL_P */ true,
+					  /* VLMAX_P */ true,
+					  dest_mode,
+					  mask_mode);
+
+  e.set_policy (TAIL_ANY);
+  e.set_policy (MASK_ANY);
+
+  e.set_vl (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
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index e5ae4e81b7a..c4588a55e04 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1306,11 +1306,22 @@  riscv_const_insns (rtx x)
 		if (satisfies_constraint_vi (x))
 		  return 1;
 
-		/* A const duplicate vector can always be broadcast from
-		   a general-purpose register.  This means we need as many
-		   insns as it takes to load the constant into the GPR
-		   and one vmv.v.x.  */
-		return 1 + riscv_const_insns (elt);
+		/* Any int/FP constants can always be broadcast from a
+		   scalar register.  Loading of a floating-point
+		   constant incurs a literal-pool access.  Allow this in
+		   order to increase vectorization possibilities.  */
+		int n = riscv_const_insns (elt);
+		if (CONST_DOUBLE_P (elt))
+		    return 1 + 4; /* vfmv.v.f + memory access.  */
+		else
+		  {
+		    /* We need as many insns as it takes to load the constant
+		       into a GPR and one vmv.v.x.  */
+		    if (n != 0)
+		      return 1 + n;
+		    else
+		      return 1 + 4; /*vmv.v.x + memory access.  */
+		  }
 	      }
 	  }
 
@@ -7209,8 +7220,8 @@  riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
        precision of the _FloatN type; evaluate all other operations and
        constants to the range and precision of the semantic type;
 
-   If we have the zfh/zhinx extensions then we support _Float16 in native
-   precision, so we should set this to 16.  */
+   If we have the zfh/zhinx/zvfh extensions then we support _Float16
+   in native precision, so we should set this to 16.  */
 static enum flt_eval_method
 riscv_excess_precision (enum excess_precision_type type)
 {
@@ -7218,7 +7229,7 @@  riscv_excess_precision (enum excess_precision_type type)
     {
     case EXCESS_PRECISION_TYPE_FAST:
     case EXCESS_PRECISION_TYPE_STANDARD:
-      return ((TARGET_ZFH || TARGET_ZHINX)
+      return ((TARGET_ZFH || TARGET_ZHINX || TARGET_ZVFH)
 		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
 		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
     case EXCESS_PRECISION_TYPE_IMPLICIT:
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 139d2b74d7c..e6040c1981c 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -317,6 +317,34 @@  (define_mode_iterator VF [
   (VNx16DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 128")
 ])
 
+;; This iterator is the same as above but with TARGET_VECTOR_ELEN_FP_16
+;; changed to TARGET_ZVFH.  TARGET_VECTOR_ELEN_FP_16 is also true for
+;; TARGET_ZVFHMIN while we actually disable all instructions apart from
+;; load, store and convert for it.
+;; Consequently the autovec expanders should also only be enabled with
+;; TARGET_ZVFH.
+(define_mode_iterator VF_AUTO [
+  (VNx1HF "TARGET_ZVFH && TARGET_MIN_VLEN < 128")
+  (VNx2HF "TARGET_ZVFH")
+  (VNx4HF "TARGET_ZVFH")
+  (VNx8HF "TARGET_ZVFH")
+  (VNx16HF "TARGET_ZVFH")
+  (VNx32HF "TARGET_ZVFH && TARGET_MIN_VLEN > 32")
+  (VNx64HF "TARGET_ZVFH && TARGET_MIN_VLEN >= 128")
+
+  (VNx1SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN < 128")
+  (VNx2SF "TARGET_VECTOR_ELEN_FP_32")
+  (VNx4SF "TARGET_VECTOR_ELEN_FP_32")
+  (VNx8SF "TARGET_VECTOR_ELEN_FP_32")
+  (VNx16SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN > 32")
+  (VNx32SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 128")
+  (VNx1DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN < 128")
+  (VNx2DF "TARGET_VECTOR_ELEN_FP_64")
+  (VNx4DF "TARGET_VECTOR_ELEN_FP_64")
+  (VNx8DF "TARGET_VECTOR_ELEN_FP_64")
+  (VNx16DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 128")
+])
+
 (define_mode_iterator VI_HAS_HALF [
    VNx2SI VNx4SI VNx8SI (VNx16SI "TARGET_MIN_VLEN > 32")
    (VNx32SI "TARGET_MIN_VLEN >= 128")
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-run.c
index 4f6c8e773c3..5db0a3c79be 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-run.c
@@ -51,7 +51,9 @@ 
  RUN(int32_t, -3)	\
  RUN(uint32_t, 4)	\
  RUN(int64_t, -5)	\
- RUN(uint64_t, 6)    \
+ RUN(uint64_t, 6)	\
+ RUN(float, -5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, -7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, -7)	\
@@ -59,7 +61,9 @@ 
  RUN2(int32_t, -9)	\
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, -11)	\
- RUN2(uint64_t, 12)   \
+ RUN2(uint64_t, 12)	\
+ RUN2(float, -11)	\
+ RUN2(double, 12)	\
  RUN3M(int8_t, 13)	\
  RUN3(uint8_t, 14)	\
  RUN3M(int16_t, 13)	\
@@ -67,7 +71,9 @@ 
  RUN3M(int32_t, 15)	\
  RUN3(uint32_t, 16)	\
  RUN3M(int64_t, 17)	\
- RUN3(uint64_t, 18)
+ RUN3(uint64_t, 18)	\
+ RUN3(float, 17)	\
+ RUN3M(double, 18)	\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv32gcv.c
index 2d094749c6a..cd0da74d8a5 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv32gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vadd-template.h"
 
 /* { dg-final { scan-assembler-times {\tvadd\.vv} 16 } } */
 /* { dg-final { scan-assembler-times {\tvadd\.vi} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfadd\.vv} 9 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv64gcv.c
index 4a1dc41c34a..30c3ef7bd4f 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-rv64gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vadd-template.h"
 
 /* { dg-final { scan-assembler-times {\tvadd\.vv} 16 } } */
 /* { dg-final { scan-assembler-times {\tvadd\.vi} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfadd\.vv} 9 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-template.h
index fecf2947691..e05b9c76275 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-template.h
@@ -41,6 +41,9 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
  TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
@@ -49,6 +52,9 @@ 
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
  TEST2_TYPE(uint64_t)   \
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
  TEST3M_TYPE(int8_t)	\
  TEST3_TYPE(uint8_t)	\
  TEST3M_TYPE(int16_t)	\
@@ -56,6 +62,9 @@ 
  TEST3M_TYPE(int32_t)	\
  TEST3_TYPE(uint32_t)	\
  TEST3M_TYPE(int64_t)	\
- TEST3_TYPE(uint64_t)
+ TEST3_TYPE(uint64_t)   \
+ TEST3M_TYPE(_Float16)	\
+ TEST3_TYPE(float)	\
+ TEST3M_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-zvfh-run.c
new file mode 100644
index 00000000000..1a11fe0fb30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vadd-zvfh-run.c
@@ -0,0 +1,54 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vadd-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];	  			\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = 0;             		\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vadd_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == VAL);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = 0;            		\
+  vadds_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == VAL);
+
+#define RUN3(TYPE,VAL)				\
+  TYPE ai##TYPE[SZ];	  	        	\
+  for (int i = 0; i < SZ; i++)			\
+    ai##TYPE[i] = VAL;				\
+  vaddi_##TYPE (ai##TYPE, ai##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (ai##TYPE[i] == VAL + 15);
+
+#define RUN3M(TYPE,VAL)				\
+  TYPE aim##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    aim##TYPE[i] = VAL;				\
+  vaddim_##TYPE (aim##TYPE, aim##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (aim##TYPE[i] == VAL - 16);
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+ RUN3M(_Float16, 17)	\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-run.c
index c4fd81f4bf2..2cd841f0118 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-run.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vdiv-template.h"
 
@@ -36,6 +36,8 @@ 
  RUN(uint32_t, 4)	\
  RUN(int64_t, -5)	\
  RUN(uint64_t, 6)	\
+ RUN(float, -5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, -7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, -7)	\
@@ -43,7 +45,9 @@ 
  RUN2(int32_t, -9)	\
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, -11)	\
- RUN2(uint64_t, 12)
+ RUN2(uint64_t, 12)	\
+ RUN2(float, -11)	\
+ RUN2(double, 12)	\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
index 9f059ebc84c..604d9acb038 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vdiv-template.h"
 
@@ -8,3 +8,8 @@ 
 
 /* { dg-final { scan-assembler-times {\tvdiv\.vv} 14 } } */
 /* { dg-final { scan-assembler-times {\tvdivu\.vv} 14 } } */
+
+/* Division by constant is done by calculating a reciprocal and
+   then multiplying.  Hence we do not expect 6 vfdivs.  */
+/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {\tvfmul\.vv} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
index cd5d30b8974..26884035d57 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vdiv-template.h"
 
@@ -8,3 +8,8 @@ 
 
 /* { dg-final { scan-assembler-times {\tvdiv\.vv} 14 } } */
 /* { dg-final { scan-assembler-times {\tvdivu\.vv} 14 } } */
+
+/* Division by constant is done by calculating a reciprocal and
+   then multiplying.  Hence we do not expect 6 vfdivs.  */
+/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {\tvfmul\.vv} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-template.h
index fd9199722b6..7b0f579d1c9 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-template.h
@@ -25,6 +25,9 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
  TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
@@ -32,6 +35,9 @@ 
  TEST2_TYPE(int32_t)	\
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
- TEST2_TYPE(uint64_t)
+ TEST2_TYPE(uint64_t)	\
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-zvfh-run.c
new file mode 100644
index 00000000000..7407a4f3e6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-zvfh-run.c
@@ -0,0 +1,37 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
+
+#include "vdiv-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];	  			\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = VAL * 3;       		\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vdiv_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == 3);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = VAL * 5;			\
+  vdivs_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == 5);
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-run.c
index 668f848694b..20aceb32b05 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-run.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmax-template.h"
 
@@ -27,6 +27,7 @@ 
   for (int i = 0; i < SZ; i++)			\
     assert (as##TYPE[i] == 0 > VAL ? 0 : VAL);
 
+
 #define RUN_ALL()	\
  RUN(int8_t, -1)	\
  RUN(uint8_t, 2)	\
@@ -36,6 +37,8 @@ 
  RUN(uint32_t, 4)	\
  RUN(int64_t, -5)	\
  RUN(uint64_t, 6)	\
+ RUN(float, -5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, -7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, -7)	\
@@ -43,7 +46,9 @@ 
  RUN2(int32_t, -9)	\
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, -11)	\
- RUN2(uint64_t, 12)
+ RUN2(uint64_t, 12)	\
+ RUN2(float, -11)	\
+ RUN2(double, 12)	\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv32gcv.c
index 7b217d990a6..fbfa3ab057d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv32gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmax-template.h"
 
 /* { dg-final { scan-assembler-times {\tvmax\.vv} 8 } } */
 /* { dg-final { scan-assembler-times {\tvmaxu\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmax\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv64gcv.c
index 1b7f8c6be16..cf01ebc65f8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-rv64gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmax-template.h"
 
 /* { dg-final { scan-assembler-times {\tvmax\.vv} 8 } } */
 /* { dg-final { scan-assembler-times {\tvmaxu\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmax\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-template.h
index 6deb5126c7d..54828cd922a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-template.h
@@ -25,6 +25,9 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
  TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
@@ -32,6 +35,9 @@ 
  TEST2_TYPE(int32_t)	\
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
- TEST2_TYPE(uint64_t)
+ TEST2_TYPE(uint64_t)	\
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-zvfh-run.c
new file mode 100644
index 00000000000..60226b00f2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmax-zvfh-run.c
@@ -0,0 +1,38 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
+
+#include "vmax-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = 0;             		\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vmax_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == 0 > VAL ? 0 : VAL);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = 0;				\
+  vmaxs_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == 0 > VAL ? 0 : VAL);
+
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-run.c
index 63c05a119a9..2babc7012e7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-run.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmin-template.h"
 
@@ -35,7 +35,9 @@ 
  RUN(int32_t, -3)	\
  RUN(uint32_t, 4)	\
  RUN(int64_t, -5)	\
- RUN(uint64_t, 6)    \
+ RUN(uint64_t, 6)	\
+ RUN(float, -5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, -7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, -7)	\
@@ -43,7 +45,9 @@ 
  RUN2(int32_t, -9)	\
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, -11)	\
- RUN2(uint64_t, 12)
+ RUN2(uint64_t, 12)	\
+ RUN2(float, -11)	\
+ RUN2(double, 12)	\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv32gcv.c
index bf826ebf53a..87640732b3b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv32gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmin-template.h"
 
 /* { dg-final { scan-assembler-times {\tvmin\.vv} 8 } } */
 /* { dg-final { scan-assembler-times {\tvminu\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmin\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv64gcv.c
index f57d4369006..193dacc82c5 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-rv64gcv.c
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmin-template.h"
 
 /* { dg-final { scan-assembler-times {\tvmin\.vv} 8 } } */
 /* { dg-final { scan-assembler-times {\tvminu\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {\tvfmin\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-template.h
index 1225d5aca64..ca0d4e751e3 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-template.h
@@ -25,6 +25,9 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
  TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
@@ -32,6 +35,9 @@ 
  TEST2_TYPE(int32_t)	\
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
- TEST2_TYPE(uint64_t)
+ TEST2_TYPE(uint64_t)	\
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-zvfh-run.c
new file mode 100644
index 00000000000..2f74e809b7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmin-zvfh-run.c
@@ -0,0 +1,37 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
+
+#include "vmin-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];	  			\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = 0;             		\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vmin_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == 0 < VAL ? 0 : VAL);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = 0;				\
+  vmins_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == 0 < VAL ? 0 : VAL);
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-run.c
index c560af9b85d..390e0b9a7fb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-run.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmul-template.h"
 
@@ -36,6 +36,8 @@ 
  RUN(uint32_t, 4)	\
  RUN(int64_t, -5)	\
  RUN(uint64_t, 6)	\
+ RUN(float, -5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, -7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, -7)	\
@@ -43,7 +45,9 @@ 
  RUN2(int32_t, -9)	\
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, -11)	\
- RUN2(uint64_t, 12)
+ RUN2(uint64_t, 12)	\
+ RUN2(float, -11)	\
+ RUN2(double, 12)	\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv32gcv.c
index 53d920010da..1900c21121b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv32gcv.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmul-template.h"
 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv64gcv.c
index 1624e16a53c..c8508bcc1f7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-rv64gcv.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vmul-template.h"
 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-template.h
index 33f9d87e1bb..4b81f52b065 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-template.h
@@ -25,6 +25,9 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
  TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
@@ -32,6 +35,9 @@ 
  TEST2_TYPE(int32_t)	\
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
- TEST2_TYPE(uint64_t)
+ TEST2_TYPE(uint64_t)	\
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-zvfh-run.c
new file mode 100644
index 00000000000..aa056e74178
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vmul-zvfh-run.c
@@ -0,0 +1,37 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
+
+#include "vmul-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];	  			\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = 2;				\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vadd_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == 2 * VAL);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = 3;            		\
+  vadds_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == 3 * VAL);
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vrem-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vrem-rv32gcv.c
index 7d2b478e1de..c6fe79e37b8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vrem-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vrem-rv32gcv.c
@@ -1,5 +1,4 @@ 
-/* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vrem-template.h"
 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-run.c
index fb6df757c90..28b2a0e14be 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-run.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-run.c
@@ -1,5 +1,5 @@ 
 /* { dg-do run { target { riscv_vector } } } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vsub-template.h"
 
@@ -52,6 +52,8 @@ 
  RUN(uint32_t, 4)	\
  RUN(int64_t, 5)	\
  RUN(uint64_t, 6)	\
+ RUN(float, 5)		\
+ RUN(double, 6)		\
  RUN2(int8_t, 7)	\
  RUN2(uint8_t, 8)	\
  RUN2(int16_t, 7)	\
@@ -60,6 +62,8 @@ 
  RUN2(uint32_t, 10)	\
  RUN2(int64_t, 11)	\
  RUN2(uint64_t, 12)	\
+ RUN2(float, 11)	\
+ RUN2(double, 12)	\
  RUN3(int8_t)		\
  RUN3(uint8_t)		\
  RUN3(int16_t)		\
@@ -68,6 +72,8 @@ 
  RUN3(uint32_t)		\
  RUN3(int64_t)		\
  RUN3(uint64_t)		\
+ RUN3(float)		\
+ RUN3(double)		\
  RUN4(int8_t)		\
  RUN4(uint8_t)		\
  RUN4(int16_t)		\
@@ -75,7 +81,9 @@ 
  RUN4(int32_t)		\
  RUN4(uint32_t)		\
  RUN4(int64_t)		\
- RUN4(uint64_t)
+ RUN4(uint64_t)		\
+ RUN4(float)		\
+ RUN4(double)		\
 
 int main ()
 {
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv32gcv.c
index 5641432410e..f09d0664660 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv32gcv.c
@@ -1,7 +1,13 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv_zvfh -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vsub-template.h"
 
 /* { dg-final { scan-assembler-times {\tvsub\.vv} 16 } } */
 /* { dg-final { scan-assembler-times {\tvrsub\.vi} 16 } } */
+
+/* { dg-final { scan-assembler-times {\tvfsub\.vv} 12 } } */
+
+/* Do not expect vfrsub for now, because we do not properly
+   handle vop.vx and vfop.vf yet.  */
+/* { dg-final { scan-assembler-times {\tvfrsub\.vv} 0 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv64gcv.c
index 4fe0969c3a0..9f44f5fb5ab 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-rv64gcv.c
@@ -1,7 +1,13 @@ 
 /* { dg-do compile } */
-/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv_zvfh -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
 
 #include "vsub-template.h"
 
 /* { dg-final { scan-assembler-times {\tvsub\.vv} 16 } } */
 /* { dg-final { scan-assembler-times {\tvrsub\.vi} 16 } } */
+
+/* { dg-final { scan-assembler-times {\tvfsub\.vv} 12 } } */
+
+/* Do not expect vfrsub for now, because we do not properly
+   handle vop.vx and vfop.vf yet.  */
+/* { dg-final { scan-assembler-times {\tvfrsub\.vv} 0 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-template.h
index 222972d4752..d54b7ea6aa1 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-template.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-template.h
@@ -41,8 +41,11 @@ 
  TEST_TYPE(uint32_t)	\
  TEST_TYPE(int64_t)	\
  TEST_TYPE(uint64_t)    \
- TEST2_TYPE(int8_t)	\
+ TEST_TYPE(_Float16)	\
+ TEST_TYPE(float)	\
+ TEST_TYPE(double)	\
 
+ TEST2_TYPE(int8_t)	\
  TEST2_TYPE(uint8_t)	\
  TEST2_TYPE(int16_t)	\
  TEST2_TYPE(uint16_t)	\
@@ -50,6 +53,9 @@ 
  TEST2_TYPE(uint32_t)	\
  TEST2_TYPE(int64_t)	\
  TEST2_TYPE(uint64_t)
+ TEST2_TYPE(_Float16)	\
+ TEST2_TYPE(float)	\
+ TEST2_TYPE(double)	\
 
  TEST3_TYPE(int8_t)	\
  TEST3_TYPE(uint8_t)	\
@@ -59,6 +65,9 @@ 
  TEST3_TYPE(uint32_t)	\
  TEST3_TYPE(int64_t)	\
  TEST3_TYPE(uint64_t)	\
+ TEST3_TYPE(_Float16)	\
+ TEST3_TYPE(float)	\
+ TEST3_TYPE(double)	\
 
  TEST4_TYPE(int8_t)	\
  TEST4_TYPE(uint8_t)	\
@@ -67,6 +76,9 @@ 
  TEST4_TYPE(int32_t)	\
  TEST4_TYPE(uint32_t)	\
  TEST4_TYPE(int64_t)	\
- TEST4_TYPE(uint64_t)
+ TEST4_TYPE(uint64_t)	\
+ TEST4_TYPE(_Float16)	\
+ TEST4_TYPE(float)	\
+ TEST4_TYPE(double)	\
 
 TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-zvfh-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-zvfh-run.c
new file mode 100644
index 00000000000..6ccec194642
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vsub-zvfh-run.c
@@ -0,0 +1,55 @@ 
+/* { dg-do run { target { riscv_vector && riscv_zvfh_hw } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */
+
+#include "vsub-template.h"
+
+#include <assert.h>
+
+#define SZ 512
+
+#define RUN(TYPE,VAL)				\
+  TYPE a##TYPE[SZ];				\
+  TYPE b##TYPE[SZ];	  			\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = 999;           		\
+    b##TYPE[i] = VAL;           		\
+  }                             		\
+  vsub_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == 999 - VAL);
+
+#define RUN2(TYPE,VAL)				\
+  TYPE as##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as##TYPE[i] = 999;            		\
+  vsubs_##TYPE (as##TYPE, as##TYPE, VAL, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as##TYPE[i] == 999 - VAL);
+
+#define RUN3(TYPE)				\
+  TYPE as2##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as2##TYPE[i] = i * 33 - 779;            	\
+  vsubi_##TYPE (as2##TYPE, as2##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as2##TYPE[i] == (TYPE)(-16 - (i * 33 - 779)));
+
+#define RUN4(TYPE)				\
+  TYPE as3##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+    as3##TYPE[i] = i * -17 + 667;            	\
+  vsubi2_##TYPE (as3##TYPE, as3##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (as3##TYPE[i] == (TYPE)(15 - (i * -17 + 667)));
+
+#define RUN_ALL()	\
+ RUN(_Float16, 4)	\
+ RUN2(_Float16, 10)	\
+ RUN3(_Float16)		\
+ RUN4(_Float16)		\
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 184fafb020f..ab2616a9a34 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1804,6 +1804,55 @@  proc check_effective_target_riscv_vector { } {
     }]
 }
 
+# Return 1 if the we can build a vector example with proper -march flags
+# and the current target can execute it, 0 otherwise.  Cache the result.
+
+proc check_effective_target_riscv_vector_hw { } {
+
+    return [check_runtime riscv_vector_hw32 {
+        int main (void)
+        {
+            asm ("vsetivli zero,8,e16,m1,ta,ma");
+            asm ("vadd.vv v8,v8,v16" : : : "v8");
+            return 0;
+        }
+    } "-march=rv32gcv -mabi=ilp32d"] || [check_runtime riscv_vector_hw64 {
+        int main (void)
+        {
+            asm ("vsetivli zero,8,e16,m1,ta,ma");
+            asm ("vadd.vv v8,v8,v16" : : : "v8");
+            return 0;
+        }
+    } "-march=rv64gcv -mabi=lp64d"]
+}
+
+# Return 1 if the we can build a Zvfh vector example with proper -march flags
+# and the current target can execute it, 0 otherwise.  Cache the result.
+
+proc check_effective_target_riscv_zvfh_hw { } {
+    if ![check_effective_target_riscv_vector_hw] then {
+        return 0
+    }
+
+    return [check_runtime riscv_zvfh_hw32 {
+        int main (void)
+        {
+            asm ("vsetivli zero,8,e16,m1,ta,ma");
+            asm ("vfadd.vv v8,v8,v16" : : : "v8");
+            return 0;
+        }
+    } "-march=rv32gcv_zvfh -mabi=ilp32d"]
+    || [check_runtime riscv_zvfh_hw64 {
+        int main (void)
+        {
+            asm ("vsetivli zero,8,e16,m1,ta,ma");
+            asm ("vfadd.vv v8,v8,v16" : : : "v8");
+            return 0;
+        }
+    } "-march=rv64gcv_zvfh -mabi=lp64d"]
+}
+
+
 # Return 1 if the target is RV32, 0 otherwise.  Cache the result.
 
 proc check_effective_target_rv32 { } {