public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-2896] RISC-V: Support CALL for RVV floating-point dynamic rounding
@ 2023-08-01  7:58 Pan Li
  0 siblings, 0 replies; only message in thread
From: Pan Li @ 2023-08-01  7:58 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:46a508ec7aee5038cc0a8800b756838ebef7f6d2

commit r14-2896-g46a508ec7aee5038cc0a8800b756838ebef7f6d2
Author: Pan Li <pan2.li@intel.com>
Date:   Wed Jul 19 11:00:52 2023 +0800

    RISC-V: Support CALL for RVV floating-point dynamic rounding
    
    In basic dynamic rounding mode, we simply ignore call instructions and
    we would like to take care of call in this PATCH.
    
    During the call, the frm may be updated or keep as is. Thus, we must
    make sure at least 2 things.
    
    1. The static frm before call should not pollute the frm value in call.
    2. The updated frm value in call should be sticky after call completed.
    
    We will perfrom some steps to make above happen.
    
    1. Mark call instruction with new mode DYN_CALL.
    2. Mark the instruction after CALL from NONE to DYN.
    3. When emit for a DYN_CALL, we will restore the frm value.
    4. When emit from a DYN_CALL, we will backup the frm value.
    
    Let's take a flow for this.
    
               +-------------+
               | Entry (DYN) | <- frrm a5
               +-------------+
              /               \
        +-------+             +-----------+
        | VFADD |             | VFADD RTZ |  <- fsrmi 1(RTZ)
        +-------+             +-----------+
              |                    |
        +-------+             +-----------+
        | CALL  |             | CALL      |  <- fsrm a5
        +-------+             +-----------+
              |                       |
    +-----------+                 +-------+
    | SHIFT     | <- frrm a5      | VFADD |  <- frrm a5
    +-----------+                 +-------+
              |                  /
    +-----------+               /
    | VFADD RUP | <- fsrm1 3(RUP)
    +-----------+             /
               \             /
                +-----------------+
                | Exit (DYN_EXIT) | <- fsrm a5
                +-----------------+
    
    When call is the last insn of one bb, we take care of it when needed
    for each insn by inserting one frm backup (frrm) insn to the end of
    the current bb.
    
    Signed-off-by: Pan Li <pan2.li@intel.com>
    Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai>
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (DYNAMIC_FRM_RTL): New macro.
            (STATIC_FRM_P): Ditto.
            (struct mode_switching_info): New struct for mode switching.
            (struct machine_function): Add new field mode switching.
            (riscv_emit_frm_mode_set): Add DYN_CALL emit.
            (riscv_frm_adjust_mode_after_call): New function for call mode.
            (riscv_frm_emit_after_call_in_bb_end): New function for emit
            insn when call as the end of bb.
            (riscv_frm_mode_needed): New function for frm mode needed.
            (frm_unknown_dynamic_p): Remove call check.
            (riscv_mode_needed): Extrac function for frm.
            (riscv_frm_mode_after): Add DYN_CALL after.
            (riscv_mode_entry): Remove backup rtl initialization.
            * config/riscv/vector.md (frm_mode): Add dyn_call.
            (fsrmsi_restore_exit): Rename to _volatile.
            (fsrmsi_restore_volatile): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/rvv/base/float-point-frm-insert-7.c: Adjust
            test cases.
            * gcc.target/riscv/rvv/base/float-point-frm-run-1.c: Ditto.
            * gcc.target/riscv/rvv/base/float-point-frm-run-2.c: Ditto.
            * gcc.target/riscv/rvv/base/float-point-frm-run-3.c: Ditto.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c: New test.
            * gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c: New test.
            * gcc.target/riscv/rvv/base/float-point-frm-run-4.c: New test.
            * gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
            * gcc.target/riscv/rvv/base/float-point-frm-run.h: New test.

Diff:
---
 gcc/config/riscv/riscv.cc                          | 144 ++++++++++++++++++---
 gcc/config/riscv/vector.md                         |   4 +-
 .../riscv/rvv/base/float-point-dynamic-frm-33.c    |  31 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-34.c    |  32 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-35.c    |  32 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-36.c    |  29 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-37.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-38.c    |  34 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-39.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-40.c    |  34 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-41.c    |  37 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-42.c    |  37 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-43.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-44.c    |  40 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-45.c    |  35 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-46.c    |  35 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-47.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-48.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-49.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-50.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-51.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-52.c    |  36 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-53.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-54.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-55.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-56.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-57.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-58.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-59.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-60.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-61.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-62.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-63.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-64.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-65.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-66.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-67.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-68.c    |  38 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-69.c    |  31 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-70.c    |  28 ++++
 .../riscv/rvv/base/float-point-dynamic-frm-71.c    |  28 ++++
 .../riscv/rvv/base/float-point-dynamic-frm-72.c    |  33 +++++
 .../riscv/rvv/base/float-point-dynamic-frm-73.c    |  39 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-74.c    |  39 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-75.c    |  39 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-76.c    |  39 ++++++
 .../riscv/rvv/base/float-point-dynamic-frm-77.c    |  20 +++
 .../riscv/rvv/base/float-point-frm-insert-7.c      |   5 +-
 .../riscv/rvv/base/float-point-frm-run-1.c         |  50 ++-----
 .../riscv/rvv/base/float-point-frm-run-2.c         |  40 +-----
 .../riscv/rvv/base/float-point-frm-run-3.c         |  40 +-----
 .../riscv/rvv/base/float-point-frm-run-4.c         |  47 +++++++
 .../riscv/rvv/base/float-point-frm-run-5.c         |  47 +++++++
 .../riscv/rvv/base/float-point-frm-run.h           |  40 ++++++
 54 files changed, 1884 insertions(+), 139 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 1eacca06b5c..b6a57d0306d 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-expr.h"
 #include "tree-vectorizer.h"
+#include "gcse.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -90,6 +91,12 @@ along with GCC; see the file COPYING3.  If not see
 /* True if bit BIT is set in VALUE.  */
 #define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0)
 
+/* Extract the backup dynamic frm rtl.  */
+#define DYNAMIC_FRM_RTL(c) ((c)->machine->mode_sw_info.dynamic_frm)
+
+/* True the mode switching has static frm, or false.  */
+#define STATIC_FRM_P(c) ((c)->machine->mode_sw_info.static_frm_p)
+
 /* Information about a function's frame layout.  */
 struct GTY(())  riscv_frame_info {
   /* The size of the frame in bytes.  */
@@ -125,6 +132,22 @@ enum riscv_privilege_levels {
   UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE
 };
 
+struct GTY(()) mode_switching_info {
+  /* The RTL variable which stores the dynamic FRM value.  We always use this
+     RTX to restore dynamic FRM rounding mode in mode switching.  */
+  rtx dynamic_frm;
+
+  /* The boolean variables indicates there is at least one static rounding
+     mode instruction in the function or not.  */
+  bool static_frm_p;
+
+  mode_switching_info ()
+    {
+      dynamic_frm = NULL_RTX;
+      static_frm_p = false;
+    }
+};
+
 struct GTY(())  machine_function {
   /* The number of extra stack bytes taken up by register varargs.
      This area is allocated by the callee at the very top of the frame.  */
@@ -148,9 +171,8 @@ struct GTY(())  machine_function {
      not be considered by the prologue and epilogue.  */
   bool reg_is_wrapped_separately[FIRST_PSEUDO_REGISTER];
 
-  /* The RTL variable which stores the dynamic FRM value.  We always use this
-     RTX to restore dynamic FRM rounding mode in mode switching.  */
-  rtx dynamic_frm;
+  /* The mode swithching information for the FRM rounding modes.  */
+  struct mode_switching_info mode_sw_info;
 };
 
 /* Information about a single argument.  */
@@ -7753,9 +7775,13 @@ riscv_static_frm_mode_p (int mode)
 static void
 riscv_emit_frm_mode_set (int mode, int prev_mode)
 {
+  rtx backup_reg = DYNAMIC_FRM_RTL (cfun);
+
+  if (prev_mode == FRM_MODE_DYN_CALL)
+    emit_insn (gen_frrmsi (backup_reg)); /* Backup frm when DYN_CALL.  */
+
   if (mode != prev_mode)
     {
-      rtx backup_reg = cfun->machine->dynamic_frm;
       /* TODO: By design, FRM_MODE_xxx used by mode switch which is
 	 different from the FRM value like FRM_RTZ defined in
 	 riscv-protos.h.  When mode switching we actually need a conversion
@@ -7765,10 +7791,14 @@ riscv_emit_frm_mode_set (int mode, int prev_mode)
 	 and then we leverage this assumption when emit.  */
       rtx frm = gen_int_mode (mode, SImode);
 
-      if (mode == FRM_MODE_DYN_EXIT && prev_mode != FRM_MODE_DYN)
+      if (mode == FRM_MODE_DYN_CALL && prev_mode != FRM_MODE_DYN)
 	/* No need to emit when prev mode is DYN already.  */
-	emit_insn (gen_fsrmsi_restore_exit (backup_reg));
-      else if (mode == FRM_MODE_DYN)
+	emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
+      else if (mode == FRM_MODE_DYN_EXIT && STATIC_FRM_P (cfun)
+	&& prev_mode != FRM_MODE_DYN && prev_mode != FRM_MODE_DYN_CALL)
+	/* No need to emit when prev mode is DYN or DYN_CALL already.  */
+	emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
+      else if (mode == FRM_MODE_DYN && prev_mode != FRM_MODE_DYN_CALL)
 	/* Restore frm value from backup when switch to DYN mode.  */
 	emit_insn (gen_fsrmsi_restore (backup_reg));
       else if (riscv_static_frm_mode_p (mode))
@@ -7797,6 +7827,88 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
 }
 
+/* Adjust the FRM_MODE_NONE insn after a call to FRM_MODE_DYN for the
+   underlying emit.  */
+
+static int
+riscv_frm_adjust_mode_after_call (rtx_insn *cur_insn, int mode)
+{
+  rtx_insn *insn = prev_nonnote_nondebug_insn_bb (cur_insn);
+
+  if (insn && CALL_P (insn))
+    return FRM_MODE_DYN;
+
+  return mode;
+}
+
+/* Insert the backup frm insn to the end of the bb if and only if the call
+   is the last insn of this bb.  */
+
+static void
+riscv_frm_emit_after_bb_end (rtx_insn *cur_insn)
+{
+  edge eg;
+  edge_iterator eg_iterator;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  FOR_EACH_EDGE (eg, eg_iterator, bb->succs)
+    {
+      start_sequence ();
+      emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+      rtx_insn *backup_insn = get_insns ();
+      end_sequence ();
+
+      if (eg->flags & EDGE_ABNORMAL)
+	insert_insn_end_basic_block (backup_insn, bb);
+      else
+	insert_insn_on_edge (backup_insn, eg);
+    }
+
+  commit_edge_insertions ();
+}
+
+/* Return mode that frm must be switched into
+   prior to the execution of insn.  */
+
+static int
+riscv_frm_mode_needed (rtx_insn *cur_insn, int code)
+{
+  if (!DYNAMIC_FRM_RTL(cfun))
+    {
+      /* The dynamic frm will be initialized only onece during cfun.  */
+      DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
+      emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+    }
+
+  if (CALL_P (cur_insn))
+    {
+      rtx_insn *insn = next_nonnote_nondebug_insn_bb (cur_insn);
+
+      if (!insn)
+	riscv_frm_emit_after_bb_end (cur_insn);
+
+      return FRM_MODE_DYN_CALL;
+    }
+
+  int mode = code >= 0 ? get_attr_frm_mode (cur_insn) : FRM_MODE_NONE;
+
+  if (mode == FRM_MODE_NONE)
+      /* After meet a call, we need to backup the frm because it may be
+	 updated during the call. Here, for each insn, we will check if
+	 the previous insn is a call or not. When previous insn is call,
+	 there will be 2 cases for the emit mode set.
+
+	 1. Current insn is not MODE_NONE, then the mode switch framework
+	    will do the mode switch from MODE_CALL to MODE_NONE natively.
+	 2. Current insn is MODE_NONE, we need to adjust the MODE_NONE to
+	    the MODE_DYN, and leave the mode switch itself to perform
+	    the emit mode set.
+       */
+    mode = riscv_frm_adjust_mode_after_call (cur_insn, mode);
+
+  return mode;
+}
+
 /* Return mode that entity must be switched into
    prior to the execution of insn.  */
 
@@ -7810,7 +7922,7 @@ riscv_mode_needed (int entity, rtx_insn *insn)
     case RISCV_VXRM:
       return code >= 0 ? get_attr_vxrm_mode (insn) : VXRM_MODE_NONE;
     case RISCV_FRM:
-      return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_NONE;
+      return riscv_frm_mode_needed (insn, code);
     default:
       gcc_unreachable ();
     }
@@ -7857,11 +7969,6 @@ frm_unknown_dynamic_p (rtx_insn *insn)
   if (reg_set_p (gen_rtx_REG (SImode, FRM_REGNUM), insn))
     return true;
 
-  /* A CALL function may contain an instruction that modifies the FRM,
-     return true in this situation.  */
-  if (CALL_P (insn))
-    return true;
-
   return false;
 }
 
@@ -7887,6 +7994,11 @@ riscv_vxrm_mode_after (rtx_insn *insn, int mode)
 static int
 riscv_frm_mode_after (rtx_insn *insn, int mode)
 {
+  STATIC_FRM_P (cfun) = STATIC_FRM_P (cfun) || riscv_static_frm_mode_p (mode);
+
+  if (CALL_P (insn))
+    return mode;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
@@ -7927,12 +8039,6 @@ riscv_mode_entry (int entity)
       return VXRM_MODE_NONE;
     case RISCV_FRM:
       {
-	if (!cfun->machine->dynamic_frm)
-	  {
-	    cfun->machine->dynamic_frm = gen_reg_rtx (SImode);
-	    emit_insn_at_entry (gen_frrmsi (cfun->machine->dynamic_frm));
-	  }
-
 	  /* According to RVV 1.0 spec, all vector floating-point operations use
 	     the dynamic rounding mode in the frm register.  Likewise in other
 	     similar places.  */
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 6ebbefc4ff6..b3c0c3dd45d 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -865,7 +865,7 @@
         (const_string "none")))
 
 ;; Defines rounding mode of an floating-point operation.
-(define_attr "frm_mode" "rne,rtz,rdn,rup,rmm,dyn,dyn_exit,none"
+(define_attr "frm_mode" "rne,rtz,rdn,rup,rmm,dyn,dyn_exit,dyn_call,none"
   (cond [(eq_attr "type" "vfalu")
          (cond
 	   [(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RNE")
@@ -992,7 +992,7 @@
 ;; The volatile fsrmsi restore is used for the exit point for the
 ;; dynamic mode switching. It will generate one volatile fsrm a5
 ;; which won't be eliminated.
-(define_insn "fsrmsi_restore_exit"
+(define_insn "fsrmsi_restore_volatile"
   [(set (reg:SI FRM_REGNUM)
 	(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
 			    UNSPECV_FRM_RESTORE_EXIT))]
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
new file mode 100644
index 00000000000..4bd520ea2af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+  vl = normalize_vl (vl);
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
new file mode 100644
index 00000000000..6c7cf7ef69c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+
+  vl = normalize_vl (vl);
+
+  return vl > 128 ? result : op2;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
new file mode 100644
index 00000000000..b7f5a6919f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
new file mode 100644
index 00000000000..4485cea24d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (vl % 4 != 0)
+    vl = normalize_vl (vl);
+
+  return vl > 16 ? result : op2;
+}
+
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
new file mode 100644
index 00000000000..a1fca1a2a3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      int count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (int i = 0; i < count; i++)
+    {
+      if (i % 2 == 0)
+        result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+      else
+        vl = normalize_vl (vl);
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
new file mode 100644
index 00000000000..8d59cae9a87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      int count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (int i = 0; i < count; i++)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+      vl = normalize_vl (vl);
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
new file mode 100644
index 00000000000..04c54877393
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      int count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (int i = 0; i < count; i++)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+      if (vl % 8 != 0)
+        vl = normalize_vl (vl);
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
new file mode 100644
index 00000000000..49cf52f739b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
new file mode 100644
index 00000000000..79ef55b2c9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
new file mode 100644
index 00000000000..1123a93997e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..2ea60ca47c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+
+  if (vl % 16 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+
+  vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..7486ed465c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t __attribute__ ((noinline))
+normalize_vl (size_t vl)
+{
+  if (vl % 4 == 0)
+    return vl;
+
+  return ((vl / 4) + 1) * 4;
+}
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+
+  vl = normalize_vl (vl);
+
+  if (vl % 16 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+
+
+  if (vl % 7 != 0)
+    vl = normalize_vl (vl);
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..3ceea105f6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	  vl = normalize_vl (vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl (vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
new file mode 100644
index 00000000000..b990fb434f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	  vl = normalize_vl (vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 3, vl);
+	  vl = normalize_vl (vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
new file mode 100644
index 00000000000..994c86e93eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_1 (vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_2 (vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
new file mode 100644
index 00000000000..4cde923abc1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+	  vl = normalize_vl_2 (vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..0b0a017cfd5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+      else
+	{
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
new file mode 100644
index 00000000000..23f72664426
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+      else
+	{
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 3, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
new file mode 100644
index 00000000000..8b564ca5f43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+      else
+	{
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
new file mode 100644
index 00000000000..b63f717b239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..647de39d66e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
new file mode 100644
index 00000000000..8c67d4bba81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
new file mode 100644
index 00000000000..61365103b40
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
new file mode 100644
index 00000000000..e5a1c356a98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..7ac9c960e65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
new file mode 100644
index 00000000000..c5f96bc45c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
new file mode 100644
index 00000000000..87d436ac146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
new file mode 100644
index 00000000000..ad3a7f81a69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
new file mode 100644
index 00000000000..8748ca66b1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
new file mode 100644
index 00000000000..8fd97b50124
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..58718c39279
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ad2d54510bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
new file mode 100644
index 00000000000..c15629d2134
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
new file mode 100644
index 00000000000..ea99831f31f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
new file mode 100644
index 00000000000..b8500303a21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
new file mode 100644
index 00000000000..1dbf6dba208
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+extern size_t normalize_vl_2 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  for (unsigned i = 0; i < count; i++)
+    {
+      if (i % 3 == 0)
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
+	  vl = normalize_vl_1 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+	}
+      else
+	{
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+	  vl = normalize_vl_2 (vl);
+	  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+	}
+    }
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 4 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
new file mode 100644
index 00000000000..b08ab1ef605
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result;
+  vfloat32m1_t f32_res = op1;
+  vint32m1_t i32_res = __riscv_vreinterpret_v_f32m1_i32m1 (op2);
+
+  if (count & vl == 0x1f)
+    i32_res = __riscv_vadd_vv_i32m1 (i32_res, i32_res, vl);
+  else
+    vl = normalize_vl_1 (vl);
+
+  f32_res = __riscv_vreinterpret_v_i32m1_f32m1 (i32_res);
+  result = __riscv_vfadd_vv_f32m1_rm (f32_res, op2, 4, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
new file mode 100644
index 00000000000..5a2b8a16952
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (count & vl == 0x1f)
+    result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+  else
+    vl = normalize_vl_1 (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
new file mode 100644
index 00000000000..185a04cc2bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (count & vl == 0x1f)
+    result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+  else
+    vl = normalize_vl_1 (vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
new file mode 100644
index 00000000000..6a07cfa6df9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 (size_t vl);
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			     unsigned count, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
+  vl = normalize_vl_1 (vl);
+
+  vint32m1_t tmp_1 = __riscv_vreinterpret_v_f32m1_i32m1 (op1);
+  vint32m1_t tmp_2 = __riscv_vreinterpret_v_f32m1_i32m1 (op2);
+
+  tmp_1 = __riscv_vadd_vv_i32m1 (tmp_1, tmp_2, vl);
+  tmp_2 = __riscv_vadd_vv_i32m1 (tmp_2, tmp_1, vl);
+  tmp_1 = __riscv_vadd_vv_i32m1 (tmp_1, tmp_2, vl);
+
+  result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+
+  return result;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
new file mode 100644
index 00000000000..91b015c51e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 ();
+extern size_t normalize_vl_2 ();
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      size_t vl, int cond)
+{
+  vfloat32m1_t result_1;
+
+  asm volatile ("#def %0" : "=vr"(result_1));
+
+  result_1 = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_1));
+
+  if (cond)
+    normalize_vl_1 ();
+  else
+    normalize_vl_2 ();
+
+  vfloat32m1_t result_2;
+
+  asm volatile ("#def %0" : "=vr"(result_2));
+
+  result_2 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 3, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_2));
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
new file mode 100644
index 00000000000..b52400e5123
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 ();
+extern size_t normalize_vl_2 ();
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      size_t vl, int cond)
+{
+  vfloat32m1_t result_1;
+
+  asm volatile ("#def %0" : "=vr"(result_1));
+
+  result_1 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 1, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_1));
+
+  if (cond)
+    normalize_vl_1 ();
+  else
+    normalize_vl_2 ();
+
+  vfloat32m1_t result_2;
+
+  asm volatile ("#def %0" : "=vr"(result_2));
+
+  result_2 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 3, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_2));
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
new file mode 100644
index 00000000000..4d3fd859637
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 ();
+extern size_t normalize_vl_2 ();
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      size_t vl, int cond)
+{
+  vfloat32m1_t result_1;
+
+  asm volatile ("#def %0" : "=vr"(result_1));
+
+  result_1 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 1, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_1));
+
+  if (cond)
+    normalize_vl_1 ();
+  else
+    normalize_vl_2 ();
+
+  vfloat32m1_t result_2;
+
+  asm volatile ("#def %0" : "=vr"(result_2));
+
+  result_2 = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_2));
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
new file mode 100644
index 00000000000..7ff106a8847
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+extern size_t normalize_vl_1 ();
+extern size_t normalize_vl_2 ();
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2,
+			      size_t vl, int cond)
+{
+  vfloat32m1_t result_1;
+
+  asm volatile ("#def %0" : "=vr"(result_1));
+
+  result_1 = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_1));
+
+  if (cond)
+    normalize_vl_1 ();
+  else
+    normalize_vl_2 ();
+
+  vfloat32m1_t result_2;
+
+  asm volatile ("#def %0" : "=vr"(result_2));
+
+  result_2 = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  asm volatile ("#use %0" : : "vr"(result_2));
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
new file mode 100644
index 00000000000..c3d12cfe04e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zbb --param=riscv-autovec-preference=fixed-vlmax -ffast-math -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+double sum(double *d)
+{
+  double sum = 0.0;
+
+  for (int i = 0; i < 8; ++i)
+    sum += d[i];
+
+  return sum;
+}
+
+/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 3 } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[01234]} } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-7.c
index 12db112dd0b..6de9d06b875 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-7.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-7.c
@@ -26,6 +26,7 @@ test_float_point_frm_static (float *out, vfloat32m1_t op1, vfloat32m1_t op2,
 }
 
 /* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 2 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 1 } } */
-/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
 /* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[axs][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
index 1b2789a924b..f3089d2b773 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
@@ -5,6 +5,8 @@
 #include <stdio.h>
 #include <stdint-gcc.h>
 
+#include "float-point-frm-run.h"
+
 #define DEFINE_TEST_FUNC(FRM) \
 vfloat32m1_t __attribute__ ((noinline)) \
 test_float_point_frm_run_##FRM (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) \
@@ -15,7 +17,7 @@ test_float_point_frm_run_##FRM (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) \
                                                                                \
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, FRM, vl);                   \
                                                                                \
-  assert_equal (FRM, get_frm (), "The value of frm should be " #FRM ".");      \
+  assert_equal (FRM, get_frm (), "The value of frm should be equal");          \
                                                                                \
   return result;                                                               \
 }
@@ -23,42 +25,6 @@ test_float_point_frm_run_##FRM (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) \
 #define RUN_TEST_FUNC(FRM, op1, op2, vl) \
   test_float_point_frm_run_##FRM (op1, op2, vl)
 
-static int
-get_frm ()
-{
-  int frm = -1;
-
-  __asm__ volatile (
-    "frrm %0"
-    :"=r"(frm)
-    :
-    :
-  );
-
-  return frm;
-}
-
-static void
-set_frm (int frm)
-{
-  __asm__ volatile (
-    "fsrm %0"
-    :
-    :"r"(frm)
-    :
-  );
-}
-
-static inline void
-assert_equal (int a, int b, char *message)
-{
-  if (a != b)
-    {
-      printf (message);
-      __builtin_abort ();
-    }
-}
-
 DEFINE_TEST_FUNC (0)
 DEFINE_TEST_FUNC (1)
 DEFINE_TEST_FUNC (2)
@@ -75,19 +41,19 @@ main ()
   set_frm (4);
 
   RUN_TEST_FUNC (0, op1, op2, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   RUN_TEST_FUNC (1, op1, op2, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   RUN_TEST_FUNC (2, op1, op2, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   RUN_TEST_FUNC (3, op1, op2, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   RUN_TEST_FUNC (4, op1, op2, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
index ec4cc26135d..8303b61eb04 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
@@ -5,41 +5,7 @@
 #include <stdio.h>
 #include <stdint-gcc.h>
 
-static int
-get_frm ()
-{
-  int frm = -1;
-
-  __asm__ volatile (
-    "frrm %0"
-    :"=r"(frm)
-    :
-    :
-  );
-
-  return frm;
-}
-
-static void
-set_frm (int frm)
-{
-  __asm__ volatile (
-    "fsrm %0"
-    :
-    :"r"(frm)
-    :
-  );
-}
-
-static inline void
-assert_equal (int a, int b, char *message)
-{
-  if (a != b)
-    {
-      fprintf (stdout, "%s, but get %d != %d\n", message, a, b);
-      __builtin_abort ();
-    }
-}
+#include "float-point-frm-run.h"
 
 vfloat32m1_t __attribute__ ((noinline))
 test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
@@ -50,7 +16,7 @@ test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
 
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   return result;
 }
@@ -65,7 +31,7 @@ main ()
   set_frm (2);
   test_float_point_frm_run (op1, op2, vl);
 
-  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+  assert_equal (2, get_frm (), "The value of frm should be equal");
 
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
index 32ed6962dc9..592ff6bd621 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
@@ -5,41 +5,7 @@
 #include <stdio.h>
 #include <stdint-gcc.h>
 
-static int
-get_frm ()
-{
-  int frm = -1;
-
-  __asm__ volatile (
-    "frrm %0"
-    :"=r"(frm)
-    :
-    :
-  );
-
-  return frm;
-}
-
-static void
-set_frm (int frm)
-{
-  __asm__ volatile (
-    "fsrm %0"
-    :
-    :"r"(frm)
-    :
-  );
-}
-
-static inline void
-assert_equal (int a, int b, char *message)
-{
-  if (a != b)
-    {
-      fprintf (stdout, "%s, but get %d != %d\n", message, a, b);
-      __builtin_abort ();
-    }
-}
+#include "float-point-frm-run.h"
 
 vfloat32m1_t __attribute__ ((noinline))
 test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
@@ -48,7 +14,7 @@ test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
 
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
 
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+  assert_equal (4, get_frm (), "The value of frm should be equal");
 
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
@@ -66,7 +32,7 @@ main ()
   set_frm (0);
   test_float_point_frm_run (op1, op2, vl);
 
-  assert_equal (0, get_frm (), "The value of frm register should be 0.");
+  assert_equal (0, get_frm (), "The value of frm should be equal");
 
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..56e46680e8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,47 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#include "float-point-frm-run.h"
+
+#define ORIGINAL_FRM 1
+
+vfloat32m1_t __attribute__ ((noinline))
+other_function (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op2;
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  assert_equal (ORIGINAL_FRM, get_frm (), "The value of frm should be equal");
+
+  return result;
+}
+
+vfloat32m1_t __attribute__ ((noinline))
+test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = {};
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+
+  assert_equal (4, get_frm (), "The value of frm should be equal");
+
+  return other_function (result, op2, vl);
+}
+
+int
+main ()
+{
+  size_t vl = 8;
+  vfloat32m1_t op1 = {};
+  vfloat32m1_t op2 = {};
+
+  set_frm (ORIGINAL_FRM);
+  test_float_point_frm_run (op1, op2, vl);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
new file mode 100644
index 00000000000..8b338f2903d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,47 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#include "float-point-frm-run.h"
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+void __attribute__ ((noinline))
+other_function ()
+{
+  set_frm (NEW_FRM);
+}
+
+vfloat32m1_t __attribute__ ((noinline))
+test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = {};
+
+  other_function ();
+  assert_equal (NEW_FRM, get_frm (), "The value of frm should be equal");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm should be equal");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (), "The value of frm should be equal");
+
+  return result;
+}
+
+int
+main ()
+{
+  size_t vl = 8;
+  vfloat32m1_t op1 = {};
+  vfloat32m1_t op2 = {};
+
+  set_frm (ORIGINAL_FRM);
+  test_float_point_frm_run (op1, op2, vl);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run.h b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run.h
new file mode 100644
index 00000000000..7dc2a10bc16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run.h
@@ -0,0 +1,40 @@
+#ifndef FLOAT_POINT_FRM_RUN_H
+#define FLOAT_POINT_FRM_RUN_H
+
+static void
+assert_equal (int a, int b, char *message)
+{
+  if (a != b)
+    {
+      printf ("%s, but get %d != %d\n", message, a, b);
+      __builtin_abort ();
+    }
+}
+
+static int
+get_frm ()
+{
+  int frm = -1;
+
+  __asm__ volatile (
+    "frrm %0"
+    :"=r"(frm)
+    :
+    :
+  );
+
+  return frm;
+}
+
+static void
+set_frm (int frm)
+{
+  __asm__ volatile (
+    "fsrm %0"
+    :
+    :"r"(frm)
+    :
+  );
+}
+
+#endif

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-01  7:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-01  7:58 [gcc r14-2896] RISC-V: Support CALL for RVV floating-point dynamic rounding Pan Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).