public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding
@ 2023-07-19  3:28 pan2.li
  2023-07-19  3:31 ` juzhe.zhong
                   ` (5 more replies)
  0 siblings, 6 replies; 49+ messages in thread
From: pan2.li @ 2023-07-19  3:28 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, pan2.li, yanzhang.wang, kito.cheng

From: Pan Li <pan2.li@intel.com>

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

Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.

Signed-off-by: Pan Li <pan2.li@intel.com>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai>

gcc/ChangeLog:

	* config/riscv/riscv.cc (struct machine_function): Add new field
	static_frm_p.
	(riscv_emit_frm_mode_set): Add DYN_CALL emit.
	(riscv_frm_mode_needed): New function for frm mode needed.
	(riscv_mode_needed): Extrac function for frm.
	(riscv_frm_mode_after): Add DYN_CALL after.
	* 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: Fix
	tests cases.
	* 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-frm-run-4.c: New test.
	* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
 gcc/config/riscv/riscv.cc                     | 73 +++++++++++++++-
 gcc/config/riscv/vector.md                    |  4 +-
 .../rvv/base/float-point-dynamic-frm-33.c     | 31 +++++++
 .../rvv/base/float-point-dynamic-frm-34.c     | 32 +++++++
 .../rvv/base/float-point-dynamic-frm-35.c     | 32 +++++++
 .../rvv/base/float-point-dynamic-frm-36.c     | 29 +++++++
 .../rvv/base/float-point-dynamic-frm-37.c     | 36 ++++++++
 .../rvv/base/float-point-dynamic-frm-38.c     | 34 ++++++++
 .../rvv/base/float-point-dynamic-frm-39.c     | 36 ++++++++
 .../rvv/base/float-point-dynamic-frm-40.c     | 34 ++++++++
 .../rvv/base/float-point-dynamic-frm-41.c     | 37 +++++++++
 .../rvv/base/float-point-dynamic-frm-42.c     | 37 +++++++++
 .../rvv/base/float-point-dynamic-frm-43.c     | 38 +++++++++
 .../rvv/base/float-point-dynamic-frm-44.c     | 40 +++++++++
 .../riscv/rvv/base/float-point-frm-insert-7.c |  5 +-
 .../riscv/rvv/base/float-point-frm-run-4.c    | 82 ++++++++++++++++++
 .../riscv/rvv/base/float-point-frm-run-5.c    | 83 +++++++++++++++++++
 17 files changed, 655 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a45c52a2437..e65520ee8a2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -151,6 +151,10 @@ struct GTY(())  machine_function {
   /* 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;
 };
 
 /* Information about a single argument.  */
@@ -7669,9 +7673,13 @@ riscv_static_frm_mode_p (int mode)
 static void
 riscv_emit_frm_mode_set (int mode, int prev_mode)
 {
+  rtx backup_reg = cfun->machine->dynamic_frm;
+
+  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
@@ -7681,9 +7689,13 @@ 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));
+	emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
+      else if (mode == FRM_MODE_DYN_EXIT && prev_mode != FRM_MODE_DYN
+	&& prev_mode != FRM_MODE_DYN_CALL && cfun->machine->static_frm_p)
+	/* 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)
 	/* Restore frm value from backup when switch to DYN mode.  */
 	emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7713,6 +7725,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
 }
 
+/* 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 (CALL_P (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_NON_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.
+
+	 TODO: this cannot handle one case if there is no instruction
+	 after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+	{
+	  if (INSN_P (insn))
+	    {
+	      if (CALL_P (insn))
+		mode = FRM_MODE_DYN;
+	      break;
+	    }
+
+	  if (insn == PREV_INSN (BB_HEAD (bb)))
+	    break;
+	}
+    }
+
+  return mode;
+}
+
 /* Return mode that entity must be switched into
    prior to the execution of insn.  */
 
@@ -7726,7 +7785,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 ();
     }
@@ -7803,6 +7862,12 @@ riscv_vxrm_mode_after (rtx_insn *insn, int mode)
 static int
 riscv_frm_mode_after (rtx_insn *insn, int mode)
 {
+  cfun->machine->static_frm_p = cfun->machine->static_frm_p
+    || riscv_static_frm_mode_p (mode);
+
+  if (CALL_P (insn))
+    return FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 215ecb9cb58..8b354e593ce 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -475,7 +475,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -610,7 +610,7 @@ (define_insn "fsrmsi_restore"
 ;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+		"The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:28 [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding pan2.li
@ 2023-07-19  3:31 ` juzhe.zhong
  2023-07-19  6:30   ` Li, Pan2
  2023-07-20  6:43 ` [PATCH v4] " pan2.li
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 49+ messages in thread
From: juzhe.zhong @ 2023-07-19  3:31 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: pan2.li, yanzhang.wang, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 32099 bytes --]

   /* 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;


Add a structure wrapper to wrap these 2 variable up.



juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2023-07-19 11:28
To: gcc-patches
CC: juzhe.zhong; pan2.li; yanzhang.wang; kito.cheng
Subject: [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com>
 
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
            +-----------------+
 
Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.
 
Signed-off-by: Pan Li <pan2.li@intel.com>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai>
 
gcc/ChangeLog:
 
* config/riscv/riscv.cc (struct machine_function): Add new field
static_frm_p.
(riscv_emit_frm_mode_set): Add DYN_CALL emit.
(riscv_frm_mode_needed): New function for frm mode needed.
(riscv_mode_needed): Extrac function for frm.
(riscv_frm_mode_after): Add DYN_CALL after.
* 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: Fix
tests cases.
* 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-frm-run-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
gcc/config/riscv/riscv.cc                     | 73 +++++++++++++++-
gcc/config/riscv/vector.md                    |  4 +-
.../rvv/base/float-point-dynamic-frm-33.c     | 31 +++++++
.../rvv/base/float-point-dynamic-frm-34.c     | 32 +++++++
.../rvv/base/float-point-dynamic-frm-35.c     | 32 +++++++
.../rvv/base/float-point-dynamic-frm-36.c     | 29 +++++++
.../rvv/base/float-point-dynamic-frm-37.c     | 36 ++++++++
.../rvv/base/float-point-dynamic-frm-38.c     | 34 ++++++++
.../rvv/base/float-point-dynamic-frm-39.c     | 36 ++++++++
.../rvv/base/float-point-dynamic-frm-40.c     | 34 ++++++++
.../rvv/base/float-point-dynamic-frm-41.c     | 37 +++++++++
.../rvv/base/float-point-dynamic-frm-42.c     | 37 +++++++++
.../rvv/base/float-point-dynamic-frm-43.c     | 38 +++++++++
.../rvv/base/float-point-dynamic-frm-44.c     | 40 +++++++++
.../riscv/rvv/base/float-point-frm-insert-7.c |  5 +-
.../riscv/rvv/base/float-point-frm-run-4.c    | 82 ++++++++++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    | 83 +++++++++++++++++++
17 files changed, 655 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a45c52a2437..e65520ee8a2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -151,6 +151,10 @@ struct GTY(())  machine_function {
   /* 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;
};
/* Information about a single argument.  */
@@ -7669,9 +7673,13 @@ riscv_static_frm_mode_p (int mode)
static void
riscv_emit_frm_mode_set (int mode, int prev_mode)
{
+  rtx backup_reg = cfun->machine->dynamic_frm;
+
+  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
@@ -7681,9 +7689,13 @@ 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));
+ emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
+      else if (mode == FRM_MODE_DYN_EXIT && prev_mode != FRM_MODE_DYN
+ && prev_mode != FRM_MODE_DYN_CALL && cfun->machine->static_frm_p)
+ /* 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7713,6 +7725,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
}
+/* 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 (CALL_P (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_NON_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.
+
+ TODO: this cannot handle one case if there is no instruction
+ after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+ {
+   if (INSN_P (insn))
+     {
+       if (CALL_P (insn))
+ mode = FRM_MODE_DYN;
+       break;
+     }
+
+   if (insn == PREV_INSN (BB_HEAD (bb)))
+     break;
+ }
+    }
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7726,7 +7785,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 ();
     }
@@ -7803,6 +7862,12 @@ riscv_vxrm_mode_after (rtx_insn *insn, int mode)
static int
riscv_frm_mode_after (rtx_insn *insn, int mode)
{
+  cfun->machine->static_frm_p = cfun->machine->static_frm_p
+    || riscv_static_frm_mode_p (mode);
+
+  if (CALL_P (insn))
+    return FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 215ecb9cb58..8b354e593ce 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -475,7 +475,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -610,7 +610,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1
 
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:31 ` juzhe.zhong
@ 2023-07-19  6:30   ` Li, Pan2
  0 siblings, 0 replies; 49+ messages in thread
From: Li, Pan2 @ 2023-07-19  6:30 UTC (permalink / raw)
  To: juzhe.zhong, gcc-patches; +Cc: Wang, Yanzhang, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 32918 bytes --]

Thanks Juzhe for review, updated PATCH v2 with rvv.exp/riscv.exp passed as below.

https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624864.html

Pan

From: juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai>
Sent: Wednesday, July 19, 2023 11:31 AM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Li, Pan2 <pan2.li@intel.com>; Wang, Yanzhang <yanzhang.wang@intel.com>; kito.cheng <kito.cheng@gmail.com>
Subject: Re: [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding

   /* 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;


Add a structure wrapper to wrap these 2 variable up.

________________________________
juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>

From: pan2.li<mailto:pan2.li@intel.com>
Date: 2023-07-19 11:28
To: gcc-patches<mailto:gcc-patches@gcc.gnu.org>
CC: juzhe.zhong<mailto:juzhe.zhong@rivai.ai>; pan2.li<mailto:pan2.li@intel.com>; yanzhang.wang<mailto:yanzhang.wang@intel.com>; kito.cheng<mailto:kito.cheng@gmail.com>
Subject: [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>

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

Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.

Signed-off-by: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>>

gcc/ChangeLog:

* config/riscv/riscv.cc (struct machine_function): Add new field
static_frm_p.
(riscv_emit_frm_mode_set): Add DYN_CALL emit.
(riscv_frm_mode_needed): New function for frm mode needed.
(riscv_mode_needed): Extrac function for frm.
(riscv_frm_mode_after): Add DYN_CALL after.
* 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: Fix
tests cases.
* 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-frm-run-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
gcc/config/riscv/riscv.cc                     | 73 +++++++++++++++-
gcc/config/riscv/vector.md                    |  4 +-
.../rvv/base/float-point-dynamic-frm-33.c     | 31 +++++++
.../rvv/base/float-point-dynamic-frm-34.c     | 32 +++++++
.../rvv/base/float-point-dynamic-frm-35.c     | 32 +++++++
.../rvv/base/float-point-dynamic-frm-36.c     | 29 +++++++
.../rvv/base/float-point-dynamic-frm-37.c     | 36 ++++++++
.../rvv/base/float-point-dynamic-frm-38.c     | 34 ++++++++
.../rvv/base/float-point-dynamic-frm-39.c     | 36 ++++++++
.../rvv/base/float-point-dynamic-frm-40.c     | 34 ++++++++
.../rvv/base/float-point-dynamic-frm-41.c     | 37 +++++++++
.../rvv/base/float-point-dynamic-frm-42.c     | 37 +++++++++
.../rvv/base/float-point-dynamic-frm-43.c     | 38 +++++++++
.../rvv/base/float-point-dynamic-frm-44.c     | 40 +++++++++
.../riscv/rvv/base/float-point-frm-insert-7.c |  5 +-
.../riscv/rvv/base/float-point-frm-run-4.c    | 82 ++++++++++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    | 83 +++++++++++++++++++
17 files changed, 655 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a45c52a2437..e65520ee8a2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -151,6 +151,10 @@ struct GTY(())  machine_function {
   /* 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;
};
/* Information about a single argument.  */
@@ -7669,9 +7673,13 @@ riscv_static_frm_mode_p (int mode)
static void
riscv_emit_frm_mode_set (int mode, int prev_mode)
{
+  rtx backup_reg = cfun->machine->dynamic_frm;
+
+  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
@@ -7681,9 +7689,13 @@ 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));
+ emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
+      else if (mode == FRM_MODE_DYN_EXIT && prev_mode != FRM_MODE_DYN
+ && prev_mode != FRM_MODE_DYN_CALL && cfun->machine->static_frm_p)
+ /* 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7713,6 +7725,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
}
+/* 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 (CALL_P (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_NON_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.
+
+ TODO: this cannot handle one case if there is no instruction
+ after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+ {
+   if (INSN_P (insn))
+     {
+       if (CALL_P (insn))
+ mode = FRM_MODE_DYN;
+       break;
+     }
+
+   if (insn == PREV_INSN (BB_HEAD (bb)))
+     break;
+ }
+    }
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7726,7 +7785,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 ();
     }
@@ -7803,6 +7862,12 @@ riscv_vxrm_mode_after (rtx_insn *insn, int mode)
static int
riscv_frm_mode_after (rtx_insn *insn, int mode)
{
+  cfun->machine->static_frm_p = cfun->machine->static_frm_p
+    || riscv_static_frm_mode_p (mode);
+
+  if (CALL_P (insn))
+    return FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 215ecb9cb58..8b354e593ce 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -475,7 +475,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -610,7 +610,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
--
2.34.1



^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:28 [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding pan2.li
  2023-07-19  3:31 ` juzhe.zhong
@ 2023-07-20  6:43 ` pan2.li
  2023-07-20  6:47   ` juzhe.zhong
  2023-07-21  3:11   ` juzhe.zhong
  2023-07-23 13:11 ` [PATCH v5] " pan2.li
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 49+ messages in thread
From: pan2.li @ 2023-07-20  6:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, kito.cheng, pan2.li, yanzhang.wang

From: Pan Li <pan2.li@intel.com>

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

Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.

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_mode_needed): New function for frm mode needed.
	(riscv_mode_needed): Extrac function for frm.
	(riscv_frm_mode_after): Add DYN_CALL after.
	* 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-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-frm-run-4.c: New test.
	* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
 gcc/config/riscv/riscv.cc                     | 100 ++++++++++++++++--
 gcc/config/riscv/vector.md                    |   4 +-
 .../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++++
 .../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++++
 .../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++++
 .../rvv/base/float-point-dynamic-frm-36.c     |  29 +++++
 .../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++++
 .../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++++
 .../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++++
 .../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++++
 .../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++++
 .../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++++
 .../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++++
 .../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++++
 .../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++++
 .../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++++
 .../rvv/base/float-point-dynamic-frm-70.c     |  28 +++++
 .../rvv/base/float-point-dynamic-frm-71.c     |  28 +++++
 .../riscv/rvv/base/float-point-frm-insert-7.c |   5 +-
 .../riscv/rvv/base/float-point-frm-run-4.c    |  82 ++++++++++++++
 .../riscv/rvv/base/float-point-frm-run-5.c    |  83 +++++++++++++++
 44 files changed, 1657 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..5ffd8945b6b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -90,6 +90,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 +131,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 +170,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
 };
 
 /* Information about a single argument.  */
@@ -7709,9 +7729,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
@@ -7721,9 +7745,13 @@ 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));
+	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)
 	/* Restore frm value from backup when switch to DYN mode.  */
 	emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7781,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
 }
 
+/* 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 (CALL_P (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_NON_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.
+
+	 TODO: this cannot handle one case if there is no instruction
+	 after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+	{
+	  if (INSN_P (insn))
+	    {
+	      if (CALL_P (insn))
+		mode = FRM_MODE_DYN;
+	      break;
+	    }
+
+	  if (insn == PREV_INSN (BB_HEAD (bb)))
+	    break;
+	}
+    }
+
+  return mode;
+}
+
 /* Return mode that entity must be switched into
    prior to the execution of insn.  */
 
@@ -7766,7 +7841,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 ();
     }
@@ -7843,6 +7918,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
@@ -7883,10 +7963,10 @@ riscv_mode_entry (int entity)
       return VXRM_MODE_NONE;
     case RISCV_FRM:
       {
-	if (!cfun->machine->dynamic_frm)
+	if (!DYNAMIC_FRM_RTL(cfun))
 	  {
-	    cfun->machine->dynamic_frm = gen_reg_rtx (SImode);
-	    emit_insn_at_entry (gen_frrmsi (cfun->machine->dynamic_frm));
+	    DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
+	    emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
 	  }
 
 	  /* According to RVV 1.0 spec, all vector floating-point operations use
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
 ;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+		"The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-20  6:43 ` [PATCH v4] " pan2.li
@ 2023-07-20  6:47   ` juzhe.zhong
  2023-07-21  3:11   ` juzhe.zhong
  1 sibling, 0 replies; 49+ messages in thread
From: juzhe.zhong @ 2023-07-20  6:47 UTC (permalink / raw)
  To: pan2.li, gcc-patches
  Cc: Kito.cheng, pan2.li, yanzhang.wang, jeffreyalaw, Robin Dapp

[-- Attachment #1: Type: text/plain, Size: 78761 bytes --]

LGTM from my side but plz wait for comments from other reviewers.



juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2023-07-20 14:43
To: gcc-patches
CC: juzhe.zhong; kito.cheng; pan2.li; yanzhang.wang
Subject: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com>
 
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
            +-----------------+
 
Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.
 
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_mode_needed): New function for frm mode needed.
(riscv_mode_needed): Extrac function for frm.
(riscv_frm_mode_after): Add DYN_CALL after.
* 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-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-frm-run-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
gcc/config/riscv/riscv.cc                     | 100 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 +++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 +++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 +++++
.../riscv/rvv/base/float-point-frm-insert-7.c |   5 +-
.../riscv/rvv/base/float-point-frm-run-4.c    |  82 ++++++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 +++++++++++++++
44 files changed, 1657 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..5ffd8945b6b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -90,6 +90,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 +131,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 +170,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7729,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
@@ -7721,9 +7745,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7781,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
}
+/* 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 (CALL_P (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_NON_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.
+
+ TODO: this cannot handle one case if there is no instruction
+ after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+ {
+   if (INSN_P (insn))
+     {
+       if (CALL_P (insn))
+ mode = FRM_MODE_DYN;
+       break;
+     }
+
+   if (insn == PREV_INSN (BB_HEAD (bb)))
+     break;
+ }
+    }
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7841,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 ();
     }
@@ -7843,6 +7918,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,10 +7963,10 @@ riscv_mode_entry (int entity)
       return VXRM_MODE_NONE;
     case RISCV_FRM:
       {
- if (!cfun->machine->dynamic_frm)
+ if (!DYNAMIC_FRM_RTL(cfun))
  {
-     cfun->machine->dynamic_frm = gen_reg_rtx (SImode);
-     emit_insn_at_entry (gen_frrmsi (cfun->machine->dynamic_frm));
+     DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
+     emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
  }
  /* According to RVV 1.0 spec, all vector floating-point operations use
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1
 
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-20  6:43 ` [PATCH v4] " pan2.li
  2023-07-20  6:47   ` juzhe.zhong
@ 2023-07-21  3:11   ` juzhe.zhong
  2023-07-21  6:44     ` Li, Pan2
  1 sibling, 1 reply; 49+ messages in thread
From: juzhe.zhong @ 2023-07-21  3:11 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: Kito.cheng, pan2.li, yanzhang.wang

[-- Attachment #1: Type: text/plain, Size: 79507 bytes --]

-      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));
+	emit_insn (gen_fsrmsi_restore_volatile (backup_reg));

No, I don't think for DYN_CALL, you need to emit restore_volatile.
It should be normal restore.


-(define_insn "fsrmsi_restore_exit"
+(define_insn "fsrmsi_restore_volatile"
No need to change it, recover it back to restore_exit.
The volatile restore should always be only used for exit.


Add one more test:

vfadd (static)

CALL

....
....                         ->   add a bunch integer RVV intrinsic (Ideally it should be only one backup frm insn after CALL).
...


vfadd (static)






juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2023-07-20 14:43
To: gcc-patches
CC: juzhe.zhong; kito.cheng; pan2.li; yanzhang.wang
Subject: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com>
 
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
            +-----------------+
 
Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.
 
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_mode_needed): New function for frm mode needed.
(riscv_mode_needed): Extrac function for frm.
(riscv_frm_mode_after): Add DYN_CALL after.
* 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-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-frm-run-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
gcc/config/riscv/riscv.cc                     | 100 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 +++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 +++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 +++++
.../riscv/rvv/base/float-point-frm-insert-7.c |   5 +-
.../riscv/rvv/base/float-point-frm-run-4.c    |  82 ++++++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 +++++++++++++++
44 files changed, 1657 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..5ffd8945b6b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -90,6 +90,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 +131,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 +170,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7729,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
@@ -7721,9 +7745,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7781,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
}
+/* 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 (CALL_P (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_NON_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.
+
+ TODO: this cannot handle one case if there is no instruction
+ after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+ {
+   if (INSN_P (insn))
+     {
+       if (CALL_P (insn))
+ mode = FRM_MODE_DYN;
+       break;
+     }
+
+   if (insn == PREV_INSN (BB_HEAD (bb)))
+     break;
+ }
+    }
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7841,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 ();
     }
@@ -7843,6 +7918,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,10 +7963,10 @@ riscv_mode_entry (int entity)
       return VXRM_MODE_NONE;
     case RISCV_FRM:
       {
- if (!cfun->machine->dynamic_frm)
+ if (!DYNAMIC_FRM_RTL(cfun))
  {
-     cfun->machine->dynamic_frm = gen_reg_rtx (SImode);
-     emit_insn_at_entry (gen_frrmsi (cfun->machine->dynamic_frm));
+     DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
+     emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
  }
  /* According to RVV 1.0 spec, all vector floating-point operations use
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1
 
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-21  3:11   ` juzhe.zhong
@ 2023-07-21  6:44     ` Li, Pan2
  0 siblings, 0 replies; 49+ messages in thread
From: Li, Pan2 @ 2023-07-21  6:44 UTC (permalink / raw)
  To: juzhe.zhong, gcc-patches; +Cc: Kito.cheng, Wang, Yanzhang

[-- Attachment #1: Type: text/plain, Size: 80523 bytes --]

Thanks Juzhe for reviewing.

The volatile should be present here as EXIT scenario. When we fsrm a5 (aka restore frm or define frm) before a call,
but the call will not use the frm value and then it will be eliminated later. Thus we need to mark this insn as volatile.

And will add the tests to PATCH v5.

Pan

From: juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai>
Sent: Friday, July 21, 2023 11:11 AM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Kito.cheng <kito.cheng@sifive.com>; Li, Pan2 <pan2.li@intel.com>; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding


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

+       emit_insn (gen_fsrmsi_restore_volatile (backup_reg));

No, I don't think for DYN_CALL, you need to emit restore_volatile.
It should be normal restore.



-(define_insn "fsrmsi_restore_exit"

+(define_insn "fsrmsi_restore_volatile"
No need to change it, recover it back to restore_exit.
The volatile restore should always be only used for exit.


Add one more test:

vfadd (static)

CALL

....
....                         ->   add a bunch integer RVV intrinsic (Ideally it should be only one backup frm insn after CALL).
...


vfadd (static)




________________________________
juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>

From: pan2.li<mailto:pan2.li@intel.com>
Date: 2023-07-20 14:43
To: gcc-patches<mailto:gcc-patches@gcc.gnu.org>
CC: juzhe.zhong<mailto:juzhe.zhong@rivai.ai>; kito.cheng<mailto:kito.cheng@sifive.com>; pan2.li<mailto:pan2.li@intel.com>; yanzhang.wang<mailto:yanzhang.wang@intel.com>
Subject: [PATCH v4] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>

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

Please *NOTE* some corn cases like no instruction after a call is not
well handled, and will be coverred in another PATCH(s) soon.

Signed-off-by: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai<mailto: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_mode_needed): New function for frm mode needed.
(riscv_mode_needed): Extrac function for frm.
(riscv_frm_mode_after): Add DYN_CALL after.
* 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-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-frm-run-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-frm-run-5.c: New test.
---
gcc/config/riscv/riscv.cc                     | 100 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 +++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 +++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 +++++
.../riscv/rvv/base/float-point-frm-insert-7.c |   5 +-
.../riscv/rvv/base/float-point-frm-run-4.c    |  82 ++++++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 +++++++++++++++
44 files changed, 1657 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..5ffd8945b6b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -90,6 +90,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 +131,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 +170,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7729,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
@@ -7721,9 +7745,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7781,53 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
     }
}
+/* 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 (CALL_P (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_NON_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.
+
+ TODO: this cannot handle one case if there is no instruction
+ after a call, we will take care of it soon.
+       */
+      rtx_insn *insn;
+      basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+      for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+ {
+   if (INSN_P (insn))
+     {
+       if (CALL_P (insn))
+ mode = FRM_MODE_DYN;
+       break;
+     }
+
+   if (insn == PREV_INSN (BB_HEAD (bb)))
+     break;
+ }
+    }
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7841,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 ();
     }
@@ -7843,6 +7918,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,10 +7963,10 @@ riscv_mode_entry (int entity)
       return VXRM_MODE_NONE;
     case RISCV_FRM:
       {
- if (!cfun->machine->dynamic_frm)
+ if (!DYNAMIC_FRM_RTL(cfun))
  {
-     cfun->machine->dynamic_frm = gen_reg_rtx (SImode);
-     emit_insn_at_entry (gen_frrmsi (cfun->machine->dynamic_frm));
+     DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
+     emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
  }
  /* According to RVV 1.0 spec, all vector floating-point operations use
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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-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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
--
2.34.1



^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:28 [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding pan2.li
  2023-07-19  3:31 ` juzhe.zhong
  2023-07-20  6:43 ` [PATCH v4] " pan2.li
@ 2023-07-23 13:11 ` pan2.li
  2023-07-24  0:53   ` juzhe.zhong
  2023-07-24  2:42 ` [PATCH v6] " pan2.li
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 49+ messages in thread
From: pan2.li @ 2023-07-23 13:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, kito.cheng, pan2.li, yanzhang.wang

From: Pan Li <pan2.li@intel.com>

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_reconcile_call_as_bb_end): New function for call as
	the last insn of bb.
	(riscv_frm_mode_needed): New function for frm mode needed.
	(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-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/config/riscv/riscv.cc                     | 150 ++++++++++++++++--
 gcc/config/riscv/vector.md                    |   4 +-
 .../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++
 .../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++
 .../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++
 .../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
 .../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++
 .../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++
 .../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++
 .../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++
 .../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++
 .../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++
 .../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-72.c     |  33 ++++
 .../rvv/base/float-point-dynamic-frm-73.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-74.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-75.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-76.c     |  39 +++++
 .../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-4.c    |  82 ++++++++++
 .../riscv/rvv/base/float-point-frm-run-5.c    |  83 ++++++++++
 50 files changed, 1913 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..bd2cf8176a7 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,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
 };
 
 /* Information about a single argument.  */
@@ -7709,9 +7730,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
@@ -7721,9 +7746,13 @@ 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));
+	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)
 	/* Restore frm value from backup when switch to DYN mode.  */
 	emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7782,102 @@ 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)
+{
+  rtx_insn *insn;
+  int mode = FRM_MODE_NONE;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+    {
+      if (INSN_P (insn))
+	{
+	  if (CALL_P (insn))
+	    mode = FRM_MODE_DYN;
+	  break;
+	}
+
+      if (insn == BB_HEAD (bb))
+	break;
+    }
+
+  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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
+{
+  rtx_insn *insn;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  gcc_assert (CALL_P (cur_insn));
+
+  if (cur_insn != BB_END (bb))
+    {
+      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
+	{
+	  if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
+	    return;
+
+	  if (insn == BB_END (bb))
+	    break;
+	}
+    }
+
+  /* Then we need to emit backup inst to the end of bb.  */
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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))
+    {
+      riscv_frm_reconcile_call_as_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_NON_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);
+
+  return mode;
+}
+
 /* Return mode that entity must be switched into
    prior to the execution of insn.  */
 
@@ -7766,7 +7891,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 ();
     }
@@ -7843,6 +7968,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
@@ -7883,12 +8013,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 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
 ;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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..ad599b8ef67
--- /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]+} 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-75.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
new file mode 100644
index 00000000000..76752e4af28
--- /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]+} 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-76.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
new file mode 100644
index 00000000000..dd8e870c787
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+		"The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-23 13:11 ` [PATCH v5] " pan2.li
@ 2023-07-24  0:53   ` juzhe.zhong
  2023-07-24  1:51     ` Li, Pan2
  0 siblings, 1 reply; 49+ messages in thread
From: juzhe.zhong @ 2023-07-24  0:53 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: Kito.cheng, pan2.li, yanzhang.wang

[-- Attachment #1: Type: text/plain, Size: 90092 bytes --]

Overall LGTM from my side. 
But we should  wait for Kito's review.



juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2023-07-23 21:11
To: gcc-patches
CC: juzhe.zhong; kito.cheng; pan2.li; yanzhang.wang
Subject: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com>
 
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_reconcile_call_as_bb_end): New function for call as
the last insn of bb.
(riscv_frm_mode_needed): New function for frm mode needed.
(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-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/config/riscv/riscv.cc                     | 150 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-72.c     |  33 ++++
.../rvv/base/float-point-dynamic-frm-73.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-74.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-75.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-76.c     |  39 +++++
.../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-4.c    |  82 ++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 ++++++++++
50 files changed, 1913 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..bd2cf8176a7 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,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7730,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
@@ -7721,9 +7746,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7782,102 @@ 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)
+{
+  rtx_insn *insn;
+  int mode = FRM_MODE_NONE;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+    {
+      if (INSN_P (insn))
+ {
+   if (CALL_P (insn))
+     mode = FRM_MODE_DYN;
+   break;
+ }
+
+      if (insn == BB_HEAD (bb))
+ break;
+    }
+
+  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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
+{
+  rtx_insn *insn;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  gcc_assert (CALL_P (cur_insn));
+
+  if (cur_insn != BB_END (bb))
+    {
+      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
+ {
+   if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
+     return;
+
+   if (insn == BB_END (bb))
+     break;
+ }
+    }
+
+  /* Then we need to emit backup inst to the end of bb.  */
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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))
+    {
+      riscv_frm_reconcile_call_as_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_NON_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);
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7891,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 ();
     }
@@ -7843,6 +7968,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,12 +8013,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 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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..ad599b8ef67
--- /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]+} 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-75.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
new file mode 100644
index 00000000000..76752e4af28
--- /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]+} 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-76.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
new file mode 100644
index 00000000000..dd8e870c787
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1
 
 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-24  0:53   ` juzhe.zhong
@ 2023-07-24  1:51     ` Li, Pan2
  2023-07-24  2:45       ` Li, Pan2
  0 siblings, 1 reply; 49+ messages in thread
From: Li, Pan2 @ 2023-07-24  1:51 UTC (permalink / raw)
  To: juzhe.zhong, gcc-patches; +Cc: Kito.cheng, Wang, Yanzhang

[-- Attachment #1: Type: text/plain, Size: 90878 bytes --]

Thanks Juzhe for reviewing, looks some conflicts with upstream, and will send the PATCH v6 after passed all the tests.

Pan

From: juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai>
Sent: Monday, July 24, 2023 8:54 AM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Kito.cheng <kito.cheng@sifive.com>; Li, Pan2 <pan2.li@intel.com>; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding

Overall LGTM from my side.
But we should  wait for Kito's review.

________________________________
juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>

From: pan2.li<mailto:pan2.li@intel.com>
Date: 2023-07-23 21:11
To: gcc-patches<mailto:gcc-patches@gcc.gnu.org>
CC: juzhe.zhong<mailto:juzhe.zhong@rivai.ai>; kito.cheng<mailto:kito.cheng@sifive.com>; pan2.li<mailto:pan2.li@intel.com>; yanzhang.wang<mailto:yanzhang.wang@intel.com>
Subject: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>

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<mailto:pan2.li@intel.com>>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai<mailto: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_reconcile_call_as_bb_end): New function for call as
the last insn of bb.
(riscv_frm_mode_needed): New function for frm mode needed.
(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-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/config/riscv/riscv.cc                     | 150 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-72.c     |  33 ++++
.../rvv/base/float-point-dynamic-frm-73.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-74.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-75.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-76.c     |  39 +++++
.../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-4.c    |  82 ++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 ++++++++++
50 files changed, 1913 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..bd2cf8176a7 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,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7730,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
@@ -7721,9 +7746,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7782,102 @@ 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)
+{
+  rtx_insn *insn;
+  int mode = FRM_MODE_NONE;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+    {
+      if (INSN_P (insn))
+ {
+   if (CALL_P (insn))
+     mode = FRM_MODE_DYN;
+   break;
+ }
+
+      if (insn == BB_HEAD (bb))
+ break;
+    }
+
+  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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
+{
+  rtx_insn *insn;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  gcc_assert (CALL_P (cur_insn));
+
+  if (cur_insn != BB_END (bb))
+    {
+      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
+ {
+   if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
+     return;
+
+   if (insn == BB_END (bb))
+     break;
+ }
+    }
+
+  /* Then we need to emit backup inst to the end of bb.  */
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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))
+    {
+      riscv_frm_reconcile_call_as_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_NON_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);
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7891,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 ();
     }
@@ -7843,6 +7968,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,12 +8013,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 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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..ad599b8ef67
--- /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]+} 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-75.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
new file mode 100644
index 00000000000..76752e4af28
--- /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]+} 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-76.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
new file mode 100644
index 00000000000..dd8e870c787
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+ "The value of frm register should be NEW_FRM.");
+
+  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;
+}
--
2.34.1



^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:28 [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding pan2.li
                   ` (2 preceding siblings ...)
  2023-07-23 13:11 ` [PATCH v5] " pan2.li
@ 2023-07-24  2:42 ` pan2.li
  2023-07-24 10:28   ` Robin Dapp
  2023-07-25  5:51 ` [PATCH v7] " pan2.li
  2023-07-28  1:15 ` [PATCH v8] " pan2.li
  5 siblings, 1 reply; 49+ messages in thread
From: pan2.li @ 2023-07-24  2:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, kito.cheng, pan2.li, yanzhang.wang

From: Pan Li <pan2.li@intel.com>

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_reconcile_call_as_bb_end): New function for call as
	the last insn of bb.
	(riscv_frm_mode_needed): New function for frm mode needed.
	(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-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/config/riscv/riscv.cc                     | 150 ++++++++++++++++--
 gcc/config/riscv/vector.md                    |   4 +-
 .../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++
 .../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++
 .../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++
 .../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
 .../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++
 .../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++
 .../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++
 .../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++
 .../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++
 .../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++
 .../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-72.c     |  33 ++++
 .../rvv/base/float-point-dynamic-frm-73.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-74.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-75.c     |  39 +++++
 .../rvv/base/float-point-dynamic-frm-76.c     |  39 +++++
 .../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-4.c    |  82 ++++++++++
 .../riscv/rvv/base/float-point-frm-run-5.c    |  83 ++++++++++
 50 files changed, 1913 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..bd2cf8176a7 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,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
 };
 
 /* Information about a single argument.  */
@@ -7709,9 +7730,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
@@ -7721,9 +7746,13 @@ 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));
+	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)
 	/* Restore frm value from backup when switch to DYN mode.  */
 	emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7782,102 @@ 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)
+{
+  rtx_insn *insn;
+  int mode = FRM_MODE_NONE;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+    {
+      if (INSN_P (insn))
+	{
+	  if (CALL_P (insn))
+	    mode = FRM_MODE_DYN;
+	  break;
+	}
+
+      if (insn == BB_HEAD (bb))
+	break;
+    }
+
+  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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
+{
+  rtx_insn *insn;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  gcc_assert (CALL_P (cur_insn));
+
+  if (cur_insn != BB_END (bb))
+    {
+      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
+	{
+	  if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
+	    return;
+
+	  if (insn == BB_END (bb))
+	    break;
+	}
+    }
+
+  /* Then we need to emit backup inst to the end of bb.  */
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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))
+    {
+      riscv_frm_reconcile_call_as_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_NON_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);
+
+  return mode;
+}
+
 /* Return mode that entity must be switched into
    prior to the execution of insn.  */
 
@@ -7766,7 +7891,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 ();
     }
@@ -7843,6 +7968,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
@@ -7883,12 +8013,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 f745888127c..05fd7600ba4 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -686,7 +686,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,none"
         (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")
@@ -813,7 +813,7 @@ (define_insn "fsrmsi_restore"
 ;; 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..d2a17ad715f
--- /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]+} 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-43.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
new file mode 100644
index 00000000000..50e1da2c3c1
--- /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]+} 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-44.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
new file mode 100644
index 00000000000..a66ca89308b
--- /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]+} 3 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 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-45.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
new file mode 100644
index 00000000000..d9c1ef29450
--- /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]+} 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-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..2c3481b980e
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..4aeae2ee0cf
--- /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]+} 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-49.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
new file mode 100644
index 00000000000..350bd4924eb
--- /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]+} 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-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..8737ab930aa
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..a73d414866b
--- /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]+} 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-53.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
new file mode 100644
index 00000000000..510210b4f5a
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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..52c99039564
--- /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]+} 5 } } */
+/* { 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..a70fc19b5c7
--- /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]+} 3 } } */
+/* { 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..803ec80b5de
--- /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]+} 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-57.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
new file mode 100644
index 00000000000..846aece4307
--- /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]+} 5 } } */
+/* { 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..06c7fcf1b89
--- /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]+} 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-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..0ae9c67ce86
--- /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]+} 3 } } */
+/* { 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..1dd5a63b381
--- /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]+} 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-63.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
new file mode 100644
index 00000000000..f73383fc279
--- /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]+} 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-64.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
new file mode 100644
index 00000000000..ed6f22c41d1
--- /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]+} 4 } } */
+/* { 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..3e43aecd913
--- /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]+} 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-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..344701f3cb5
--- /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]+} 4 } } */
+/* { 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..ad599b8ef67
--- /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]+} 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-75.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
new file mode 100644
index 00000000000..76752e4af28
--- /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]+} 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-76.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
new file mode 100644
index 00000000000..dd8e870c787
--- /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-times {frrm\s+[axs][0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 2 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+		"The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-24  1:51     ` Li, Pan2
@ 2023-07-24  2:45       ` Li, Pan2
  0 siblings, 0 replies; 49+ messages in thread
From: Li, Pan2 @ 2023-07-24  2:45 UTC (permalink / raw)
  To: juzhe.zhong, gcc-patches; +Cc: Kito.cheng, Wang, Yanzhang

[-- Attachment #1: Type: text/plain, Size: 23515 bytes --]

Passed the riscv.exp/rvv.exp in both rv32 and rv64 in PATCH v6 as below.

https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625315.html

Pan

From: Li, Pan2
Sent: Monday, July 24, 2023 9:52 AM
To: 'juzhe.zhong@rivai.ai' <juzhe.zhong@rivai.ai>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Kito.cheng <kito.cheng@sifive.com>; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: RE: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding

Thanks Juzhe for reviewing, looks some conflicts with upstream, and will send the PATCH v6 after passed all the tests.

Pan

From: juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai> <juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>>
Sent: Monday, July 24, 2023 8:54 AM
To: Li, Pan2 <pan2.li@intel.com<mailto:pan2.li@intel.com>>; gcc-patches <gcc-patches@gcc.gnu.org<mailto:gcc-patches@gcc.gnu.org>>
Cc: Kito.cheng <kito.cheng@sifive.com<mailto:kito.cheng@sifive.com>>; Li, Pan2 <pan2.li@intel.com<mailto:pan2.li@intel.com>>; Wang, Yanzhang <yanzhang.wang@intel.com<mailto:yanzhang.wang@intel.com>>
Subject: Re: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding

Overall LGTM from my side.
But we should  wait for Kito's review.

________________________________
juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>

From: pan2.li<mailto:pan2.li@intel.com>
Date: 2023-07-23 21:11
To: gcc-patches<mailto:gcc-patches@gcc.gnu.org>
CC: juzhe.zhong<mailto:juzhe.zhong@rivai.ai>; kito.cheng<mailto:kito.cheng@sifive.com>; pan2.li<mailto:pan2.li@intel.com>; yanzhang.wang<mailto:yanzhang.wang@intel.com>
Subject: [PATCH v5] RISC-V: Support CALL for RVV floating-point dynamic rounding
From: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>

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<mailto:pan2.li@intel.com>>
Co-Authored-By: Juzhe-Zhong <juzhe.zhong@rivai.ai<mailto: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_reconcile_call_as_bb_end): New function for call as
the last insn of bb.
(riscv_frm_mode_needed): New function for frm mode needed.
(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-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/config/riscv/riscv.cc                     | 150 ++++++++++++++++--
gcc/config/riscv/vector.md                    |   4 +-
.../rvv/base/float-point-dynamic-frm-33.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-34.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-35.c     |  32 ++++
.../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
.../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-38.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-40.c     |  34 ++++
.../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
.../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-44.c     |  40 +++++
.../rvv/base/float-point-dynamic-frm-45.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-46.c     |  35 ++++
.../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
.../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
.../rvv/base/float-point-dynamic-frm-69.c     |  31 ++++
.../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
.../rvv/base/float-point-dynamic-frm-72.c     |  33 ++++
.../rvv/base/float-point-dynamic-frm-73.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-74.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-75.c     |  39 +++++
.../rvv/base/float-point-dynamic-frm-76.c     |  39 +++++
.../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-4.c    |  82 ++++++++++
.../riscv/rvv/base/float-point-frm-run-5.c    |  83 ++++++++++
50 files changed, 1913 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..bd2cf8176a7 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,7 @@ 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;
+  struct mode_switching_info mode_sw_info;
};
/* Information about a single argument.  */
@@ -7709,9 +7730,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
@@ -7721,9 +7746,13 @@ 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));
+ 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)
/* Restore frm value from backup when switch to DYN mode.  */
emit_insn (gen_fsrmsi_restore (backup_reg));
@@ -7753,6 +7782,102 @@ 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)
+{
+  rtx_insn *insn;
+  int mode = FRM_MODE_NONE;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
+    {
+      if (INSN_P (insn))
+ {
+   if (CALL_P (insn))
+     mode = FRM_MODE_DYN;
+   break;
+ }
+
+      if (insn == BB_HEAD (bb))
+ break;
+    }
+
+  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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
+{
+  rtx_insn *insn;
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  gcc_assert (CALL_P (cur_insn));
+
+  if (cur_insn != BB_END (bb))
+    {
+      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
+ {
+   if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
+     return;
+
+   if (insn == BB_END (bb))
+     break;
+ }
+    }
+
+  /* Then we need to emit backup inst to the end of bb.  */
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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))
+    {
+      riscv_frm_reconcile_call_as_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_NON_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);
+
+  return mode;
+}
+
/* Return mode that entity must be switched into
    prior to the execution of insn.  */
@@ -7766,7 +7891,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 ();
     }
@@ -7843,6 +7968,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
@@ -7883,12 +8013,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 69680de2600..63b2d3a9b82 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -694,7 +694,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,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")
@@ -829,7 +829,7 @@ (define_insn "fsrmsi_restore"
;; 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))]
--
2.34.1



^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-24  2:42 ` [PATCH v6] " pan2.li
@ 2023-07-24 10:28   ` Robin Dapp
  2023-07-24 11:59     ` Li, Pan2
  0 siblings, 1 reply; 49+ messages in thread
From: Robin Dapp @ 2023-07-24 10:28 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: rdapp.gcc, juzhe.zhong, kito.cheng, yanzhang.wang

Hi Pan,

> +  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
> +    {
> +      if (INSN_P (insn))
> +	{
> +	  if (CALL_P (insn))
> +	    mode = FRM_MODE_DYN;
> +	  break;
> +	}
> +
> +      if (insn == BB_HEAD (bb))
> +	break;
> +    }
> +
> +  return mode;
> +}

Does prev_nonnote_nondebug_insn_bb help here?  In general, we scan
back here to the last insn and "recover" if it was a call?  Why
can't we set the proper value already before exiting the function?

I guess the more general question is more towards call-clobbered or
not?  In this patch we assume the rounding mode is call clobbered
and restore it ourselves.  Has there been any kind of consensus
on this?  Intuitively I would have expected a function that requires
a non-standard rounding mode to set and restore it itself. 

> +
> +/* 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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
> +{
> +  rtx_insn *insn;
> +  basic_block bb = BLOCK_FOR_INSN (cur_insn);
> +
> +  gcc_assert (CALL_P (cur_insn));
> +
> +  if (cur_insn != BB_END (bb))
> +    {
> +      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
> +	{
> +	  if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
> +	    return;

What about nondebug insns?  Also maybe next_nonnote_nondebug_insn_bb
helps?  How about splitting the function in detection and emit?
I.e. bb_ends_in_call (or so) and the emit part.  That way it
could be more obvious in "needed" what needs to be done.

Are we handling sibcalls and tail calls properly here?

In general I'm still a bit wary that we are checking mode != prev_mode
but cannot really pinpoint why.  I would have hoped that the generic
code only calls us when this check is unnecessary and if not the
"needed" hook should be adjusted.

I also find it a bit odd to emit instructions when checking
if another mode is needed.  If what's required cannot be accomplished
with the current common code, shouldn't we rather try to amend that?

Regards
 Robin


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-24 10:28   ` Robin Dapp
@ 2023-07-24 11:59     ` Li, Pan2
  2023-07-24 12:03       ` Li, Pan2
  0 siblings, 1 reply; 49+ messages in thread
From: Li, Pan2 @ 2023-07-24 11:59 UTC (permalink / raw)
  To: Robin Dapp, gcc-patches; +Cc: juzhe.zhong, kito.cheng, Wang, Yanzhang

Thanks Robin for comments.

>> Does prev_nonnote_nondebug_insn_bb help here?  In general, we scan
>> back here to the last insn and "recover" if it was a call?  Why
>> can't we set the proper value already before exiting the function?

Good to learn prev_nonnote_nondebug_insn_bb, will have a try here.
First we mark the call as DYN_CALL. We expect the insn next to the call to emit the backup insn.
However, if next instruction is DYN_ONE, the mode switching it self will never call emit. Thus, for each
Insn is DYN_NONE, we will reset it to DYN if the last insn is call and let the mode switching to emit properly.

When meet a call, we assume the rounding mode will be clobbered.

>> What about nondebug insns?  Also maybe next_nonnote_nondebug_insn_bb
>> helps?  How about splitting the function in detection and emit?
>> I.e. bb_ends_in_call (or so) and the emit part.  That way it
>> could be more obvious in "needed" what needs to be done.

The point here is that the call may be the last insn of current bb. Then we have chance to emit backup insn AFTER
the call, because the emit by default emit the insn before current insn.

Thus we try to make up this during the needed process, I know this may not be a good idea but it is the only way
I can locate shortly. I may try to find another way if we can control the insn emit location for each insn.

Pan

-----Original Message-----
From: Robin Dapp <rdapp.gcc@gmail.com> 
Sent: Monday, July 24, 2023 6:29 PM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org
Cc: rdapp.gcc@gmail.com; juzhe.zhong@rivai.ai; kito.cheng@sifive.com; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding

Hi Pan,

> +  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
> +    {
> +      if (INSN_P (insn))
> +	{
> +	  if (CALL_P (insn))
> +	    mode = FRM_MODE_DYN;
> +	  break;
> +	}
> +
> +      if (insn == BB_HEAD (bb))
> +	break;
> +    }
> +
> +  return mode;
> +}

Does prev_nonnote_nondebug_insn_bb help here?  In general, we scan
back here to the last insn and "recover" if it was a call?  Why
can't we set the proper value already before exiting the function?

I guess the more general question is more towards call-clobbered or
not?  In this patch we assume the rounding mode is call clobbered
and restore it ourselves.  Has there been any kind of consensus
on this?  Intuitively I would have expected a function that requires
a non-standard rounding mode to set and restore it itself. 

> +
> +/* 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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
> +{
> +  rtx_insn *insn;
> +  basic_block bb = BLOCK_FOR_INSN (cur_insn);
> +
> +  gcc_assert (CALL_P (cur_insn));
> +
> +  if (cur_insn != BB_END (bb))
> +    {
> +      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
> +	{
> +	  if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
> +	    return;

What about nondebug insns?  Also maybe next_nonnote_nondebug_insn_bb
helps?  How about splitting the function in detection and emit?
I.e. bb_ends_in_call (or so) and the emit part.  That way it
could be more obvious in "needed" what needs to be done.

Are we handling sibcalls and tail calls properly here?

In general I'm still a bit wary that we are checking mode != prev_mode
but cannot really pinpoint why.  I would have hoped that the generic
code only calls us when this check is unnecessary and if not the
"needed" hook should be adjusted.

I also find it a bit odd to emit instructions when checking
if another mode is needed.  If what's required cannot be accomplished
with the current common code, shouldn't we rather try to amend that?

Regards
 Robin


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-24 11:59     ` Li, Pan2
@ 2023-07-24 12:03       ` Li, Pan2
  0 siblings, 0 replies; 49+ messages in thread
From: Li, Pan2 @ 2023-07-24 12:03 UTC (permalink / raw)
  To: Robin Dapp, gcc-patches; +Cc: juzhe.zhong, kito.cheng, Wang, Yanzhang

Fix some typo inline,  sorry for inconvenience.

-----Original Message-----
From: Li, Pan2 
Sent: Monday, July 24, 2023 7:59 PM
To: Robin Dapp <rdapp.gcc@gmail.com>; gcc-patches@gcc.gnu.org
Cc: juzhe.zhong@rivai.ai; kito.cheng@sifive.com; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: RE: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding

Thanks Robin for comments.

>> Does prev_nonnote_nondebug_insn_bb help here?  In general, we scan
>> back here to the last insn and "recover" if it was a call?  Why
>> can't we set the proper value already before exiting the function?

Good to learn prev_nonnote_nondebug_insn_bb, will have a try here.
First we mark the call as DYN_CALL. We expect the insn next to the call to emit the backup insn.
However, if next instruction is DYN_NONE, the mode switching it self will never call emit. Thus, for each
Insn is DYN_NONE, we will reset it to DYN if the last insn is call and let the mode switching to emit properly.

When meet a call, we assume the rounding mode will be clobbered.

>> What about nondebug insns?  Also maybe next_nonnote_nondebug_insn_bb
>> helps?  How about splitting the function in detection and emit?
>> I.e. bb_ends_in_call (or so) and the emit part.  That way it
>> could be more obvious in "needed" what needs to be done.

The point here is that the call may be the last insn of current bb. Then we have chance to emit backup insn AFTER
the call, because the emit by default emit the insn before current insn.

Thus we try to make up this during the needed process, I know this may not be a good idea but it is the only way
I can locate shortly. I may try to find another way if we can control the insn emit location for each insn.

Pan

-----Original Message-----
From: Robin Dapp <rdapp.gcc@gmail.com> 
Sent: Monday, July 24, 2023 6:29 PM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org
Cc: rdapp.gcc@gmail.com; juzhe.zhong@rivai.ai; kito.cheng@sifive.com; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v6] RISC-V: Support CALL for RVV floating-point dynamic rounding

Hi Pan,

> +  for (insn = PREV_INSN (cur_insn); insn; insn = PREV_INSN (insn))
> +    {
> +      if (INSN_P (insn))
> +	{
> +	  if (CALL_P (insn))
> +	    mode = FRM_MODE_DYN;
> +	  break;
> +	}
> +
> +      if (insn == BB_HEAD (bb))
> +	break;
> +    }
> +
> +  return mode;
> +}

Does prev_nonnote_nondebug_insn_bb help here?  In general, we scan
back here to the last insn and "recover" if it was a call?  Why
can't we set the proper value already before exiting the function?

I guess the more general question is more towards call-clobbered or
not?  In this patch we assume the rounding mode is call clobbered
and restore it ourselves.  Has there been any kind of consensus
on this?  Intuitively I would have expected a function that requires
a non-standard rounding mode to set and restore it itself. 

> +
> +/* 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_reconcile_call_as_bb_end (rtx_insn *cur_insn)
> +{
> +  rtx_insn *insn;
> +  basic_block bb = BLOCK_FOR_INSN (cur_insn);
> +
> +  gcc_assert (CALL_P (cur_insn));
> +
> +  if (cur_insn != BB_END (bb))
> +    {
> +      for (insn = NEXT_INSN (cur_insn); insn; insn = NEXT_INSN (insn))
> +	{
> +	  if (INSN_P (insn)) /* If there is one insn after call, do nothing.  */
> +	    return;

What about nondebug insns?  Also maybe next_nonnote_nondebug_insn_bb
helps?  How about splitting the function in detection and emit?
I.e. bb_ends_in_call (or so) and the emit part.  That way it
could be more obvious in "needed" what needs to be done.

Are we handling sibcalls and tail calls properly here?

In general I'm still a bit wary that we are checking mode != prev_mode
but cannot really pinpoint why.  I would have hoped that the generic
code only calls us when this check is unnecessary and if not the
"needed" hook should be adjusted.

I also find it a bit odd to emit instructions when checking
if another mode is needed.  If what's required cannot be accomplished
with the current common code, shouldn't we rather try to amend that?

Regards
 Robin


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v7] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-19  3:28 [PATCH v1] RISC-V: Support CALL for RVV floating-point dynamic rounding pan2.li
                   ` (3 preceding siblings ...)
  2023-07-24  2:42 ` [PATCH v6] " pan2.li
@ 2023-07-25  5:51 ` pan2.li
  2023-07-25  6:07   ` Li, Pan2
  2023-07-28  1:15 ` [PATCH v8] " pan2.li
  5 siblings, 1 reply; 49+ messages in thread
From: pan2.li @ 2023-07-25  5:51 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, kito.cheng, pan2.li, yanzhang.wang, rdapp.gcc

From: Pan Li <pan2.li@intel.com>

Update in PATCH v7:

1. Take previous/next_nonnote_nondebug_insn_bb for seeking the insn.
2. Splitting the function in detection and emit when needed.

Original commit logs:

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.
	(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-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/config/riscv/riscv.cc                     | 130 ++++++++++++++++--
 gcc/config/riscv/vector.md                    |   4 +-
 .../rvv/base/float-point-dynamic-frm-33.c     |  31 +++++
 .../rvv/base/float-point-dynamic-frm-34.c     |  32 +++++
 .../rvv/base/float-point-dynamic-frm-35.c     |  32 +++++
 .../rvv/base/float-point-dynamic-frm-36.c     |  29 ++++
 .../rvv/base/float-point-dynamic-frm-37.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-38.c     |  34 +++++
 .../rvv/base/float-point-dynamic-frm-39.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-40.c     |  34 +++++
 .../rvv/base/float-point-dynamic-frm-41.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-42.c     |  37 +++++
 .../rvv/base/float-point-dynamic-frm-43.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-44.c     |  40 ++++++
 .../rvv/base/float-point-dynamic-frm-45.c     |  35 +++++
 .../rvv/base/float-point-dynamic-frm-46.c     |  35 +++++
 .../rvv/base/float-point-dynamic-frm-47.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-48.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-49.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-50.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-51.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-52.c     |  36 +++++
 .../rvv/base/float-point-dynamic-frm-53.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-54.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-55.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-56.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-57.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-58.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-59.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-60.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-61.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-62.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-63.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-64.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-65.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-66.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-67.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-68.c     |  38 +++++
 .../rvv/base/float-point-dynamic-frm-69.c     |  31 +++++
 .../rvv/base/float-point-dynamic-frm-70.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-71.c     |  28 ++++
 .../rvv/base/float-point-dynamic-frm-72.c     |  33 +++++
 .../rvv/base/float-point-dynamic-frm-73.c     |  39 ++++++
 .../rvv/base/float-point-dynamic-frm-74.c     |  39 ++++++
 .../rvv/base/float-point-dynamic-frm-75.c     |  39 ++++++
 .../rvv/base/float-point-dynamic-frm-76.c     |  39 ++++++
 .../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-4.c    |  82 +++++++++++
 .../riscv/rvv/base/float-point-frm-run-5.c    |  83 +++++++++++
 50 files changed, 1892 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-33.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-34.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-35.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-36.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-37.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-38.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-39.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-40.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-41.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-42.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-43.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-44.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-46.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-47.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-48.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-49.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-50.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-51.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-52.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-53.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-54.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-55.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-56.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-57.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-58.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-59.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-60.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-61.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-62.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-63.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-65.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-66.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-67.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-68.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-69.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-70.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-71.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-72.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-73.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-74.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-75.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-76.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-77.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 332fa720f01..7d2d4252e5c 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.  */
@@ -7709,9 +7731,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
@@ -7721,10 +7747,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))
@@ -7753,6 +7783,79 @@ 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)
+{
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+  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_call_in_bb_end (rtx_insn *cur_insn)
+{
+  basic_block bb = BLOCK_FOR_INSN (cur_insn);
+
+  start_sequence ();
+  emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+  rtx_insn *backup_insn = get_insns ();
+  end_sequence ();
+
+  insert_insn_end_basic_block (backup_insn, bb);
+}
+
+/* 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_call_in_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_NON_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.  */
 
@@ -7766,7 +7869,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 ();
     }
@@ -7843,6 +7946,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 FRM_MODE_DYN_CALL;
+
   if (frm_unknown_dynamic_p (insn))
     return FRM_MODE_DYN;
 
@@ -7883,12 +7991,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 f745888127c..05fd7600ba4 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -686,7 +686,7 @@ (define_attr "vxrm_mode" "rnu,rne,rdn,rod,none"
         (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")
@@ -813,7 +813,7 @@ (define_insn "fsrmsi_restore"
 ;; 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
new file mode 100644
index 00000000000..5796aa53a73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-4.c
@@ -0,0 +1,82 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+
+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 ();
+    }
+}
+
+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 register should be ORIGINAL_FRM.");
+
+  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 register should be 4.");
+
+  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..208a65fcd3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-5.c
@@ -0,0 +1,83 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-options "-O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+#include <stdio.h>
+#include <stdint-gcc.h>
+
+#define ORIGINAL_FRM 1
+#define NEW_FRM 4
+
+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 ();
+    }
+}
+
+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 register should be NEW_FRM.");
+
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  assert_equal (NEW_FRM, get_frm (),
+		"The value of frm register should be NEW_FRM.");
+
+  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;
+}
-- 
2.34.1


^ permalink raw reply	[flat|nested] 49+ messages in thread

* RE: [PATCH v7] RISC-V: Support CALL for RVV floating-point dynamic rounding
  2023-07-25  5:51 `