diff mbox series

[v1] RISC-V: Support basic floating-point dynamic rounding mode

Message ID 20230714025024.1408869-1-pan2.li@intel.com
State New
Headers show
Series [v1] RISC-V: Support basic floating-point dynamic rounding mode | expand

Commit Message

Li, Pan2 via Gcc-patches July 14, 2023, 2:50 a.m. UTC
From: Pan Li <pan2.li@intel.com>

This patch would like to support the basic floating-point dynamic
rounding modes for the RVV.

We implement the dynamic rounding mode by below steps.
1. Set entry to DYN and exit to DYN_EXIT.
2. Add one rtl variable into machine_function for backup/restore.
3. Backup frm value when entry.
4. Restore frm value when exit and prev mode is not DYN.
5. Restore frm when mode switching to DYN.
6. Set frm when mode switching to STATIC.

Take one flow to describe the scenarios.

           +-------------+
           | Entry (DYN) | <- frrm a5
           +-------------+
          /               \
    +-------+            +-----------+
    | VFADD | <- fsrm a5 | VFADD RTZ | <- fsrmi 1(RTZ)
    +-------+            +-----------+
          |                    |
    +-------+            +-----------+
    | VFADD |            | VFADD RTZ |
    +-------+            +-----------+
          |                       |
+-----------+                 +-------+
| VFADD RUP | <- fsrmi 3(RUP) | VFADD | <- fsrm a5
+-----------+                 +-------+
          |                  /
+-----------+               /
| VFADD RUP |              /
+-----------+             /
           \             /
            +-----------------+
            | Exit (DYN_EXIT) | <- fsrm a5
            +-----------------+

Please *NOTE* inline asm and call during the cfun will be implemented
in another PATCH(s).

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.
	(riscv_static_frm_mode_p): New function.
	(riscv_emit_frm_mode_set): New function for emit FRM.
	(riscv_emit_mode_set): Extract function for FRM.
	(riscv_mode_needed): Fix the TODO.
	(riscv_mode_entry): Initial dynamic frm RTL.
	(riscv_mode_exit): Return DYN_EXIT.
	* config/riscv/riscv.md: Add rdfrm.
	* config/riscv/vector-iterators.md (unspecv): Add DYN_EXIT unspecv.
	* config/riscv/vector.md (frm_modee): Add new mode dyn_exit.
	(fsrm): Removed.
	(fsrmsi_backup): New pattern for swap.
	(fsrmsi_restore): New pattern for restore.
	(fsrmsi_restore_exit): New pattern for restore exit.
	(frrmsi): New pattern for backup.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/base/float-point-frm-insert-1.c: Adjust
	 test cases.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-10.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-2.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-3.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-4.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-5.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-6.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-7.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-8.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-insert-9.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-run-1.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-run-2.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-frm-run-3.c: Ditto.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c: New test.
	* gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c: New test.
---
 gcc/config/riscv/riscv.cc                     | 95 +++++++++++++------
 gcc/config/riscv/riscv.md                     |  2 +-
 gcc/config/riscv/vector-iterators.md          |  4 +-
 gcc/config/riscv/vector.md                    | 63 ++++++++----
 .../rvv/base/float-point-dynamic-frm-1.c      | 21 ++++
 .../rvv/base/float-point-dynamic-frm-10.c     | 26 +++++
 .../rvv/base/float-point-dynamic-frm-11.c     | 26 +++++
 .../rvv/base/float-point-dynamic-frm-12.c     | 29 ++++++
 .../rvv/base/float-point-dynamic-frm-13.c     | 29 ++++++
 .../rvv/base/float-point-dynamic-frm-14.c     | 28 ++++++
 .../rvv/base/float-point-dynamic-frm-15.c     | 28 ++++++
 .../rvv/base/float-point-dynamic-frm-16.c     | 22 +++++
 .../rvv/base/float-point-dynamic-frm-17.c     | 22 +++++
 .../rvv/base/float-point-dynamic-frm-18.c     | 25 +++++
 .../rvv/base/float-point-dynamic-frm-19.c     | 25 +++++
 .../rvv/base/float-point-dynamic-frm-2.c      | 20 ++++
 .../rvv/base/float-point-dynamic-frm-20.c     | 27 ++++++
 .../rvv/base/float-point-dynamic-frm-21.c     | 27 ++++++
 .../rvv/base/float-point-dynamic-frm-22.c     | 25 +++++
 .../rvv/base/float-point-dynamic-frm-23.c     | 25 +++++
 .../rvv/base/float-point-dynamic-frm-24.c     | 13 +++
 .../rvv/base/float-point-dynamic-frm-25.c     | 28 ++++++
 .../rvv/base/float-point-dynamic-frm-26.c     | 23 +++++
 .../rvv/base/float-point-dynamic-frm-27.c     | 30 ++++++
 .../rvv/base/float-point-dynamic-frm-28.c     | 30 ++++++
 .../rvv/base/float-point-dynamic-frm-29.c     | 28 ++++++
 .../rvv/base/float-point-dynamic-frm-3.c      | 21 ++++
 .../rvv/base/float-point-dynamic-frm-30.c     | 30 ++++++
 .../rvv/base/float-point-dynamic-frm-31.c     | 29 ++++++
 .../rvv/base/float-point-dynamic-frm-32.c     | 25 +++++
 .../rvv/base/float-point-dynamic-frm-4.c      | 21 ++++
 .../rvv/base/float-point-dynamic-frm-5.c      | 21 ++++
 .../rvv/base/float-point-dynamic-frm-6.c      | 27 ++++++
 .../rvv/base/float-point-dynamic-frm-7.c      | 27 ++++++
 .../rvv/base/float-point-dynamic-frm-8.c      | 26 +++++
 .../rvv/base/float-point-dynamic-frm-9.c      | 26 +++++
 .../riscv/rvv/base/float-point-frm-insert-1.c |  4 +-
 .../rvv/base/float-point-frm-insert-10.c      |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-2.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-3.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-4.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-5.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-6.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-7.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-8.c |  4 +-
 .../riscv/rvv/base/float-point-frm-insert-9.c |  4 +-
 .../riscv/rvv/base/float-point-frm-run-1.c    |  5 +-
 .../riscv/rvv/base/float-point-frm-run-2.c    |  5 +-
 .../riscv/rvv/base/float-point-frm-run-3.c    |  9 +-
 49 files changed, 967 insertions(+), 66 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c

Comments

juzhe.zhong@rivai.ai July 17, 2023, 1:02 a.m. UTC | #1
LGTM



juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2023-07-14 10:50
To: gcc-patches
CC: juzhe.zhong; pan2.li; yanzhang.wang; kito.cheng
Subject: [PATCH v1] RISC-V: Support basic floating-point dynamic rounding mode
From: Pan Li <pan2.li@intel.com>
 
This patch would like to support the basic floating-point dynamic
rounding modes for the RVV.
 
We implement the dynamic rounding mode by below steps.
1. Set entry to DYN and exit to DYN_EXIT.
2. Add one rtl variable into machine_function for backup/restore.
3. Backup frm value when entry.
4. Restore frm value when exit and prev mode is not DYN.
5. Restore frm when mode switching to DYN.
6. Set frm when mode switching to STATIC.
 
Take one flow to describe the scenarios.
 
           +-------------+
           | Entry (DYN) | <- frrm a5
           +-------------+
          /               \
    +-------+            +-----------+
    | VFADD | <- fsrm a5 | VFADD RTZ | <- fsrmi 1(RTZ)
    +-------+            +-----------+
          |                    |
    +-------+            +-----------+
    | VFADD |            | VFADD RTZ |
    +-------+            +-----------+
          |                       |
+-----------+                 +-------+
| VFADD RUP | <- fsrmi 3(RUP) | VFADD | <- fsrm a5
+-----------+                 +-------+
          |                  /
+-----------+               /
| VFADD RUP |              /
+-----------+             /
           \             /
            +-----------------+
            | Exit (DYN_EXIT) | <- fsrm a5
            +-----------------+
 
Please *NOTE* inline asm and call during the cfun will be implemented
in another PATCH(s).
 
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.
(riscv_static_frm_mode_p): New function.
(riscv_emit_frm_mode_set): New function for emit FRM.
(riscv_emit_mode_set): Extract function for FRM.
(riscv_mode_needed): Fix the TODO.
(riscv_mode_entry): Initial dynamic frm RTL.
(riscv_mode_exit): Return DYN_EXIT.
* config/riscv/riscv.md: Add rdfrm.
* config/riscv/vector-iterators.md (unspecv): Add DYN_EXIT unspecv.
* config/riscv/vector.md (frm_modee): Add new mode dyn_exit.
(fsrm): Removed.
(fsrmsi_backup): New pattern for swap.
(fsrmsi_restore): New pattern for restore.
(fsrmsi_restore_exit): New pattern for restore exit.
(frrmsi): New pattern for backup.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/base/float-point-frm-insert-1.c: Adjust
test cases.
* gcc.target/riscv/rvv/base/float-point-frm-insert-10.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-2.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-3.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-4.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-5.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-6.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-7.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-8.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-insert-9.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-run-1.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-run-2.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-frm-run-3.c: Ditto.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c: New test.
* gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c: New test.
---
gcc/config/riscv/riscv.cc                     | 95 +++++++++++++------
gcc/config/riscv/riscv.md                     |  2 +-
gcc/config/riscv/vector-iterators.md          |  4 +-
gcc/config/riscv/vector.md                    | 63 ++++++++----
.../rvv/base/float-point-dynamic-frm-1.c      | 21 ++++
.../rvv/base/float-point-dynamic-frm-10.c     | 26 +++++
.../rvv/base/float-point-dynamic-frm-11.c     | 26 +++++
.../rvv/base/float-point-dynamic-frm-12.c     | 29 ++++++
.../rvv/base/float-point-dynamic-frm-13.c     | 29 ++++++
.../rvv/base/float-point-dynamic-frm-14.c     | 28 ++++++
.../rvv/base/float-point-dynamic-frm-15.c     | 28 ++++++
.../rvv/base/float-point-dynamic-frm-16.c     | 22 +++++
.../rvv/base/float-point-dynamic-frm-17.c     | 22 +++++
.../rvv/base/float-point-dynamic-frm-18.c     | 25 +++++
.../rvv/base/float-point-dynamic-frm-19.c     | 25 +++++
.../rvv/base/float-point-dynamic-frm-2.c      | 20 ++++
.../rvv/base/float-point-dynamic-frm-20.c     | 27 ++++++
.../rvv/base/float-point-dynamic-frm-21.c     | 27 ++++++
.../rvv/base/float-point-dynamic-frm-22.c     | 25 +++++
.../rvv/base/float-point-dynamic-frm-23.c     | 25 +++++
.../rvv/base/float-point-dynamic-frm-24.c     | 13 +++
.../rvv/base/float-point-dynamic-frm-25.c     | 28 ++++++
.../rvv/base/float-point-dynamic-frm-26.c     | 23 +++++
.../rvv/base/float-point-dynamic-frm-27.c     | 30 ++++++
.../rvv/base/float-point-dynamic-frm-28.c     | 30 ++++++
.../rvv/base/float-point-dynamic-frm-29.c     | 28 ++++++
.../rvv/base/float-point-dynamic-frm-3.c      | 21 ++++
.../rvv/base/float-point-dynamic-frm-30.c     | 30 ++++++
.../rvv/base/float-point-dynamic-frm-31.c     | 29 ++++++
.../rvv/base/float-point-dynamic-frm-32.c     | 25 +++++
.../rvv/base/float-point-dynamic-frm-4.c      | 21 ++++
.../rvv/base/float-point-dynamic-frm-5.c      | 21 ++++
.../rvv/base/float-point-dynamic-frm-6.c      | 27 ++++++
.../rvv/base/float-point-dynamic-frm-7.c      | 27 ++++++
.../rvv/base/float-point-dynamic-frm-8.c      | 26 +++++
.../rvv/base/float-point-dynamic-frm-9.c      | 26 +++++
.../riscv/rvv/base/float-point-frm-insert-1.c |  4 +-
.../rvv/base/float-point-frm-insert-10.c      |  4 +-
.../riscv/rvv/base/float-point-frm-insert-2.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-3.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-4.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-5.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-6.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-7.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-8.c |  4 +-
.../riscv/rvv/base/float-point-frm-insert-9.c |  4 +-
.../riscv/rvv/base/float-point-frm-run-1.c    |  5 +-
.../riscv/rvv/base/float-point-frm-run-2.c    |  5 +-
.../riscv/rvv/base/float-point-frm-run-3.c    |  9 +-
49 files changed, 967 insertions(+), 66 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 6ed735d6983..a45c52a2437 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -148,6 +148,9 @@ 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;
};
/* Information about a single argument.  */
@@ -7641,6 +7644,55 @@ riscv_vectorize_preferred_vector_alignment (const_tree type)
   return TYPE_ALIGN (type);
}
+/* Return true if it is static FRM rounding mode.  */
+
+static bool
+riscv_static_frm_mode_p (int mode)
+{
+  switch (mode)
+    {
+    case FRM_MODE_RDN:
+    case FRM_MODE_RUP:
+    case FRM_MODE_RTZ:
+    case FRM_MODE_RMM:
+    case FRM_MODE_RNE:
+      return true;
+    default:
+      return false;
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implement the floating-point Mode Switching.  */
+
+static void
+riscv_emit_frm_mode_set (int mode, int prev_mode)
+{
+  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
+ function to convert the mode of mode switching to the actual
+ FRM value like FRM_RTZ.  For now, the value between the mode of
+ mode swith and the FRM value in riscv-protos.h take the same value,
+ 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)
+ /* No need to emit when prev mode is DYN already.  */
+ emit_insn (gen_fsrmsi_restore_exit (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));
+      else if (riscv_static_frm_mode_p (mode))
+ /* Set frm value when switch to static mode.  */
+ emit_insn (gen_fsrmsi_restore (frm));
+    }
+}
+
/* Implement Mode switching.  */
static void
@@ -7654,25 +7706,7 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
emit_insn (gen_vxrmsi (gen_int_mode (mode, SImode)));
       break;
     case RISCV_FRM:
-      /* Switching to the dynamic rounding mode is not necessary.  When an
- instruction requests it, it effectively uses the rounding mode already
- set in the FRM register.  All other rounding modes require us to
- switch the rounding mode via the FRM register.  */
-      if (mode != FRM_MODE_DYN && mode != prev_mode)
- {
-   /* 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
-      function to convert the mode of mode switching to the actual
-      FRM value like FRM_RTZ.  For now, the value between the mode of
-      mode swith and the FRM value in riscv-protos.h take the same value,
-      and then we leverage this assumption when emit.  */
-   rtx scaler = gen_reg_rtx (SImode);
-   rtx imm = gen_int_mode (mode, SImode);
-
-   emit_insn (gen_movsi (scaler, imm));
-   emit_insn (gen_fsrm (scaler, scaler));
- }
+      riscv_emit_frm_mode_set (mode, prev_mode);
       break;
     default:
       gcc_unreachable ();
@@ -7692,10 +7726,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:
-      /* TODO: Here we may return FRM_MODE_NONE from get_attr_frm_mode, as well
- as FRM_MODE_DYN as default.  It is kind of inconsistent and we will
- take care of it after dynamic rounding mode.  */
-      return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_DYN;
+      return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_NONE;
     default:
       gcc_unreachable ();
     }
@@ -7811,10 +7842,18 @@ riscv_mode_entry (int entity)
     case RISCV_VXRM:
       return VXRM_MODE_NONE;
     case RISCV_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.  */
-      return FRM_MODE_DYN;
+      {
+ 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.  */
+ return FRM_MODE_DYN;
+      }
     default:
       gcc_unreachable ();
     }
@@ -7831,7 +7870,7 @@ riscv_mode_exit (int entity)
     case RISCV_VXRM:
       return VXRM_MODE_NONE;
     case RISCV_FRM:
-      return FRM_MODE_DYN;
+      return FRM_MODE_DYN_EXIT;
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7988026d129..5bcec1d2234 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -391,7 +391,7 @@ (define_attr "type"
    mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
    fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
    clmul,min,max,minu,maxu,clz,ctz,cpop,
-   atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,wrfrm,vsetvl,
+   atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,wrfrm,rdfrm,vsetvl,
    vlde,vste,vldm,vstm,vlds,vsts,
    vldux,vldox,vstux,vstox,vldff,vldr,vstr,
    vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index ec49544bcf6..fdb87314014 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -81,8 +81,10 @@ (define_c_enum "unspec" [
   UNSPEC_VCOMPRESS
   UNSPEC_VLEFF
   UNSPEC_MODIFY_VL
+])
-  UNSPEC_FSRM
+(define_c_enum "unspecv" [
+  UNSPECV_FRM_RESTORE_EXIT
])
(define_mode_iterator V [
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index de944637570..215ecb9cb58 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,none"
+(define_attr "frm_mode" "rne,rtz,rdn,rup,rmm,dyn,dyn_exit,none"
   (cond
     [
       (eq_attr "type" "vfalu")
@@ -583,24 +583,51 @@ (define_insn "vxrmsi"
    (set_attr "mode" "SI")])
;; Set FRM
-(define_insn "fsrm"
-  [
-    (set
-      (reg:SI FRM_REGNUM)
-      (unspec:SI
- [
-   (match_operand:SI 0 "register_operand" "=&r")
-   (match_operand:SI 1 "register_operand" "r")
- ] UNSPEC_FSRM
-      )
-    )
-  ]
+(define_insn "fsrmsi_backup"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (reg:SI FRM_REGNUM))
+   (set (reg:SI FRM_REGNUM)
+ (match_operand:SI 1 "reg_or_int_operand" "r,i"))]
+   "TARGET_VECTOR"
+  "@
+   fsrm\t%0,%1
+   fsrmi\t%0,%1"
+  [(set_attr "type" "wrfrm,wrfrm")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "fsrmsi_restore"
+  [(set (reg:SI FRM_REGNUM)
+ (match_operand:SI 0 "reg_or_int_operand" "r,i"))]
   "TARGET_VECTOR"
-  "fsrm\t%0,%1"
-  [
-    (set_attr "type" "wrfrm")
-    (set_attr "mode" "SI")
-  ]
+  "@
+   fsrm\t%0
+   fsrmi\t%0"
+  [(set_attr "type" "wrfrm,wrfrm")
+   (set_attr "mode" "SI")]
+ )
+
+;; 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"
+  [(set (reg:SI FRM_REGNUM)
+ (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+     UNSPECV_FRM_RESTORE_EXIT))]
+  "TARGET_VECTOR"
+  "fsrm\t%0"
+  [(set_attr "type" "wrfrm")
+   (set_attr "mode" "SI")]
+)
+
+;; Read FRM
+(define_insn "frrmsi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+ (reg:SI FRM_REGNUM))]
+  "TARGET_VECTOR"
+  "frrm\t%0"
+  [(set_attr "type" "rdfrm")
+   (set_attr "mode" "SI")]
)
;; -----------------------------------------------------------------
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
new file mode 100644
index 00000000000..75af8eed123
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result;
+
+  result  = __riscv_vfadd_vv_f32m1 (op1, op2, 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 {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-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
new file mode 100644
index 00000000000..71428d6394c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (result, op2, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 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]+} 3 } } */
+/* { 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]+} 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-11.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
new file mode 100644
index 00000000000..94f8ea171b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, 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]+} 3 } } */
+/* { 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-12.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
new file mode 100644
index 00000000000..66c74958f2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+      if (i % 2 == 0)
+        result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, 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]+} 1 } } */
+/* { 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-13.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
new file mode 100644
index 00000000000..0fb84987d89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+      if (i % 2 == 0)
+        result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 1 } } */
+/* { 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-14.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
new file mode 100644
index 00000000000..ab5fc06493c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+
+      if (i % 2 == 0)
+        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]+} 3 } } */
+/* { 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]+} 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-15.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
new file mode 100644
index 00000000000..97daccad7af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+
+      if (i % 2 == 0)
+        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]+} 3 } } */
+/* { 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]} 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-16.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
new file mode 100644
index 00000000000..da710b17f7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (result, op2, vl);
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-17.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
new file mode 100644
index 00000000000..43f25179aba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, 2, vl);
+  result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 3 } } */
+/* { 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]} 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-18.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
new file mode 100644
index 00000000000..e7258254529
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-19.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
new file mode 100644
index 00000000000..c0161a1ba36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1 (op1, result, 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]+} 1 } } */
+/* { 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-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
new file mode 100644
index 00000000000..9f8ac99f294
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+  return __riscv_vfadd_vv_f32m1 (result, op2, vl);
+}
+
+/* { 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]} 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-20.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
new file mode 100644
index 00000000000..9e75b79722e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 2, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, result, 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]+} 5 } } */
+/* { 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-21.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
new file mode 100644
index 00000000000..aec56427371
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 2, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, result, 3, 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]+} 5 } } */
+/* { 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]} 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-22.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
new file mode 100644
index 00000000000..83bc26a8d78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 4, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, 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]+} 3 } } */
+/* { 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]} 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-23.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
new file mode 100644
index 00000000000..e7c51ea874e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, 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]+} 3 } } */
+/* { 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-24.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
new file mode 100644
index 00000000000..46ac8e02215
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
@@ -0,0 +1,13 @@
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t *out, vfloat32m1_t op1, size_t vl)
+{
+}
+
+/* { 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-25.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
new file mode 100644
index 00000000000..b70f531a24c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op2, result, 3, vl);
+      *(vfloat32m1_t *) out = 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]+} 1 } } */
+/* { 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-26.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
new file mode 100644
index 00000000000..78b2946b9fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = 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 {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-27.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
new file mode 100644
index 00000000000..4dba68040e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1 (op2, result, vl);
+      *(vfloat32m1_t *) (out + 16) = 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-not {frrm\s+[axs][0-9]+} } } */
+/* { 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]+} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
new file mode 100644
index 00000000000..35a37b83239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op2, result, 3, vl);
+      *(vfloat32m1_t *) (out + 16) = 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]+} 1 } } */
+/* { 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-29.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
new file mode 100644
index 00000000000..e24c2045f43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (float *in, float *out, int n, size_t vl)
+{
+  for (int i = 0; i < n; i++)
+    {
+      vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i, vl);
+      vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 4, vl);
+      __riscv_vse32_v_f32m1 (out + i, result, vl);
+    }
+
+  for (int i = 0; i < n; i++)
+    {
+      vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 100, vl);
+      vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+      __riscv_vse32_v_f32m1 (out + i + 100, result, vl);
+    }
+}
+
+/* { 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-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
new file mode 100644
index 00000000000..600ac45bb03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, 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 {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-30.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
new file mode 100644
index 00000000000..bf5772073f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (float *in, float *out, int n, int cond, size_t vl)
+{
+  for (int i = 0; i < n; i++)
+    {
+      if (cond)
+        {
+          vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 100, vl);
+          vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+          __riscv_vse32_v_f32m1 (out + i + 100, result, vl);
+        }
+      else
+        {
+          vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 200, vl);
+          vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+          __riscv_vse32_v_f32m1 (out + i + 200, result, vl);
+        }
+    }
+}
+
+/* { 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]} 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-31.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
new file mode 100644
index 00000000000..64a0c8cd2b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+       int n, float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+
+  if (n > 0)
+    {
+      result = __riscv_vfadd_vv_f32m1 (op2, result, vl);
+      *(vfloat32m1_t *) (out + 100) = 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]+} 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-32.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
new file mode 100644
index 00000000000..a24ffd799fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, int count,
+         size_t vl, float *out)
+{
+  vfloat32m1_t result = op1;
+
+  if (count == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+
+  return vl;
+}
+
+/* { 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]+} 1 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
new file mode 100644
index 00000000000..aaf912e0923
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (vl % 4 == 0)
+    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]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
new file mode 100644
index 00000000000..9149388bea1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (vl % 4 == 0)
+    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]+} 1 } } */
+/* { 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-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
new file mode 100644
index 00000000000..1541de88979
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 2, vl);
+      else
+        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]+} 1 } } */
+/* { 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-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
new file mode 100644
index 00000000000..6f24317c51a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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
+        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]+} 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-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
new file mode 100644
index 00000000000..a4846b05ab6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[asx][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[asx][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[asx][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c
new file mode 100644
index 00000000000..cfb8fca08a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 3 } } */
+/* { 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]} 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-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
index 732e0305a3d..608b3883dd0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
@@ -28,4 +28,6 @@ test_vfadd_vf_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, float32_t op2,
}
/* { 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 {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
index c46910b878c..3252f67d078 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
@@ -20,4 +20,6 @@ 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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
index 72e5d2084b3..96e10c720b8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
@@ -11,4 +11,6 @@ test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
}
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
index c9e8d0a6eaf..519537c07cb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
@@ -11,4 +11,6 @@ test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
}
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
index a288e0be628..f9e6bc36a90 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
@@ -20,4 +20,6 @@ test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
}
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
index bb77a6efc62..c3f6302384a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
@@ -20,4 +20,6 @@ test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
}
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 3 } } */
+/* { 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 {fsrmi\s+[01234]} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
index 6d896e0953e..1ef0e015d8f 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
@@ -28,4 +28,6 @@ test_vfadd_vf_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, float32_t op2,
}
/* { 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 {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\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 7b1602fd509..12db112dd0b 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,4 +26,6 @@ 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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
index 37481ddac38..cc83dae4e95 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
@@ -24,4 +24,6 @@ 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]+} 1 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
index 7ae834ad531..3b650ec2948 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
@@ -21,4 +21,6 @@ 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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
index 210c49c5e8d..245ce7d1fc0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
@@ -44,8 +44,6 @@ assert_equal (int a, int b, char *message)
vfloat32m1_t __attribute__ ((noinline))
test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
{
-  set_frm (0);
-
   vfloat32m1_t result;
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
@@ -73,7 +71,10 @@ main ()
   vfloat32m1_t op1;
   vfloat32m1_t op2;
+  set_frm (4);
   test_float_point_frm_run (op1, op2, vl);
+  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+
   return 0;
}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
index a7036529cf2..ec4cc26135d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
@@ -44,8 +44,6 @@ assert_equal (int a, int b, char *message)
vfloat32m1_t __attribute__ ((noinline))
test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
{
-  set_frm (0);
-
   vfloat32m1_t result = {};
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
@@ -64,7 +62,10 @@ main ()
   vfloat32m1_t op1 = {};
   vfloat32m1_t op2 = {};
+  set_frm (2);
   test_float_point_frm_run (op1, op2, vl);
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
   return 0;
}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
index 6924bdf6a05..32ed6962dc9 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
@@ -44,17 +44,15 @@ assert_equal (int a, int b, char *message)
vfloat32m1_t __attribute__ ((noinline))
test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
{
-  set_frm (0);
-
   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.");
+
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
-
   return result;
}
@@ -65,7 +63,10 @@ main ()
   vfloat32m1_t op1 = {};
   vfloat32m1_t op2 = {};
+  set_frm (0);
   test_float_point_frm_run (op1, op2, vl);
+  assert_equal (0, get_frm (), "The value of frm register should be 0.");
+
   return 0;
}
Jeff Law July 17, 2023, 4:59 p.m. UTC | #2
On 7/16/23 19:02, juzhe.zhong@rivai.ai wrote:
> LGTM
And as of today, that's all we need ;-)

Thanks,

Jeff
Li, Pan2 via Gcc-patches July 18, 2023, 1:19 a.m. UTC | #3
Committed, thanks Jeff and Juzhe.

Pan

-----Original Message-----
From: Jeff Law <jeffreyalaw@gmail.com> 
Sent: Tuesday, July 18, 2023 12:59 AM
To: juzhe.zhong@rivai.ai; Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Wang, Yanzhang <yanzhang.wang@intel.com>; kito.cheng <kito.cheng@gmail.com>
Subject: Re: [PATCH v1] RISC-V: Support basic floating-point dynamic rounding mode



On 7/16/23 19:02, juzhe.zhong@rivai.ai wrote:
> LGTM
And as of today, that's all we need ;-)

Thanks,

Jeff
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 6ed735d6983..a45c52a2437 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -148,6 +148,9 @@  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;
 };
 
 /* Information about a single argument.  */
@@ -7641,6 +7644,55 @@  riscv_vectorize_preferred_vector_alignment (const_tree type)
   return TYPE_ALIGN (type);
 }
 
+/* Return true if it is static FRM rounding mode.  */
+
+static bool
+riscv_static_frm_mode_p (int mode)
+{
+  switch (mode)
+    {
+    case FRM_MODE_RDN:
+    case FRM_MODE_RUP:
+    case FRM_MODE_RTZ:
+    case FRM_MODE_RMM:
+    case FRM_MODE_RNE:
+      return true;
+    default:
+      return false;
+    }
+
+  gcc_unreachable ();
+}
+
+/* Implement the floating-point Mode Switching.  */
+
+static void
+riscv_emit_frm_mode_set (int mode, int prev_mode)
+{
+  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
+	 function to convert the mode of mode switching to the actual
+	 FRM value like FRM_RTZ.  For now, the value between the mode of
+	 mode swith and the FRM value in riscv-protos.h take the same value,
+	 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)
+	/* No need to emit when prev mode is DYN already.  */
+	emit_insn (gen_fsrmsi_restore_exit (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));
+      else if (riscv_static_frm_mode_p (mode))
+	/* Set frm value when switch to static mode.  */
+	emit_insn (gen_fsrmsi_restore (frm));
+    }
+}
+
 /* Implement Mode switching.  */
 
 static void
@@ -7654,25 +7706,7 @@  riscv_emit_mode_set (int entity, int mode, int prev_mode,
 	emit_insn (gen_vxrmsi (gen_int_mode (mode, SImode)));
       break;
     case RISCV_FRM:
-      /* Switching to the dynamic rounding mode is not necessary.  When an
-	 instruction requests it, it effectively uses the rounding mode already
-	 set in the FRM register.  All other rounding modes require us to
-	 switch the rounding mode via the FRM register.  */
-      if (mode != FRM_MODE_DYN && mode != prev_mode)
-	{
-	  /* 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
-	     function to convert the mode of mode switching to the actual
-	     FRM value like FRM_RTZ.  For now, the value between the mode of
-	     mode swith and the FRM value in riscv-protos.h take the same value,
-	     and then we leverage this assumption when emit.  */
-	  rtx scaler = gen_reg_rtx (SImode);
-	  rtx imm = gen_int_mode (mode, SImode);
-
-	  emit_insn (gen_movsi (scaler, imm));
-	  emit_insn (gen_fsrm (scaler, scaler));
-	}
+      riscv_emit_frm_mode_set (mode, prev_mode);
       break;
     default:
       gcc_unreachable ();
@@ -7692,10 +7726,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:
-      /* TODO: Here we may return FRM_MODE_NONE from get_attr_frm_mode, as well
-	 as FRM_MODE_DYN as default.  It is kind of inconsistent and we will
-	 take care of it after dynamic rounding mode.  */
-      return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_DYN;
+      return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_NONE;
     default:
       gcc_unreachable ();
     }
@@ -7811,10 +7842,18 @@  riscv_mode_entry (int entity)
     case RISCV_VXRM:
       return VXRM_MODE_NONE;
     case RISCV_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.  */
-      return FRM_MODE_DYN;
+      {
+	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.  */
+	return FRM_MODE_DYN;
+      }
     default:
       gcc_unreachable ();
     }
@@ -7831,7 +7870,7 @@  riscv_mode_exit (int entity)
     case RISCV_VXRM:
       return VXRM_MODE_NONE;
     case RISCV_FRM:
-      return FRM_MODE_DYN;
+      return FRM_MODE_DYN_EXIT;
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7988026d129..5bcec1d2234 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -391,7 +391,7 @@  (define_attr "type"
    mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
    fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
    clmul,min,max,minu,maxu,clz,ctz,cpop,
-   atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,wrfrm,vsetvl,
+   atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,wrfrm,rdfrm,vsetvl,
    vlde,vste,vldm,vstm,vlds,vsts,
    vldux,vldox,vstux,vstox,vldff,vldr,vstr,
    vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index ec49544bcf6..fdb87314014 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -81,8 +81,10 @@  (define_c_enum "unspec" [
   UNSPEC_VCOMPRESS
   UNSPEC_VLEFF
   UNSPEC_MODIFY_VL
+])
 
-  UNSPEC_FSRM
+(define_c_enum "unspecv" [
+  UNSPECV_FRM_RESTORE_EXIT
 ])
 
 (define_mode_iterator V [
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index de944637570..215ecb9cb58 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,none"
+(define_attr "frm_mode" "rne,rtz,rdn,rup,rmm,dyn,dyn_exit,none"
   (cond
     [
       (eq_attr "type" "vfalu")
@@ -583,24 +583,51 @@  (define_insn "vxrmsi"
    (set_attr "mode" "SI")])
 
 ;; Set FRM
-(define_insn "fsrm"
-  [
-    (set
-      (reg:SI FRM_REGNUM)
-      (unspec:SI
-	[
-	  (match_operand:SI 0 "register_operand" "=&r")
-	  (match_operand:SI 1 "register_operand" "r")
-	] UNSPEC_FSRM
-      )
-    )
-  ]
+(define_insn "fsrmsi_backup"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(reg:SI FRM_REGNUM))
+   (set (reg:SI FRM_REGNUM)
+	(match_operand:SI 1 "reg_or_int_operand" "r,i"))]
+   "TARGET_VECTOR"
+  "@
+   fsrm\t%0,%1
+   fsrmi\t%0,%1"
+  [(set_attr "type" "wrfrm,wrfrm")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "fsrmsi_restore"
+  [(set (reg:SI FRM_REGNUM)
+	(match_operand:SI 0 "reg_or_int_operand" "r,i"))]
   "TARGET_VECTOR"
-  "fsrm\t%0,%1"
-  [
-    (set_attr "type" "wrfrm")
-    (set_attr "mode" "SI")
-  ]
+  "@
+   fsrm\t%0
+   fsrmi\t%0"
+  [(set_attr "type" "wrfrm,wrfrm")
+   (set_attr "mode" "SI")]
+ )
+
+;; 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"
+  [(set (reg:SI FRM_REGNUM)
+	(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+			    UNSPECV_FRM_RESTORE_EXIT))]
+  "TARGET_VECTOR"
+  "fsrm\t%0"
+  [(set_attr "type" "wrfrm")
+   (set_attr "mode" "SI")]
+)
+
+;; Read FRM
+(define_insn "frrmsi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(reg:SI FRM_REGNUM))]
+  "TARGET_VECTOR"
+  "frrm\t%0"
+  [(set_attr "type" "rdfrm")
+   (set_attr "mode" "SI")]
 )
 
 ;; -----------------------------------------------------------------
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
new file mode 100644
index 00000000000..75af8eed123
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-1.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result;
+
+  result  = __riscv_vfadd_vv_f32m1 (op1, op2, 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 {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-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
new file mode 100644
index 00000000000..71428d6394c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-10.c
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (result, op2, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 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]+} 3 } } */
+/* { 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]+} 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-11.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
new file mode 100644
index 00000000000..94f8ea171b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-11.c
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, 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]+} 3 } } */
+/* { 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-12.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
new file mode 100644
index 00000000000..66c74958f2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-12.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+      if (i % 2 == 0)
+        result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, 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]+} 1 } } */
+/* { 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-13.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
new file mode 100644
index 00000000000..0fb84987d89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-13.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+      if (i % 2 == 0)
+        result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 1 } } */
+/* { 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-14.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
new file mode 100644
index 00000000000..ab5fc06493c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-14.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 3, vl);
+
+      if (i % 2 == 0)
+        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]+} 3 } } */
+/* { 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]+} 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-15.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
new file mode 100644
index 00000000000..97daccad7af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-15.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1 (result, op2, vl);
+
+      if (i % 2 == 0)
+        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]+} 3 } } */
+/* { 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]} 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-16.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
new file mode 100644
index 00000000000..da710b17f7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-16.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (result, op2, vl);
+  result = __riscv_vfadd_vv_f32m1_rm (op1, result, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-17.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
new file mode 100644
index 00000000000..43f25179aba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-17.c
@@ -0,0 +1,22 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, 2, vl);
+  result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 3 } } */
+/* { 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]} 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-18.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
new file mode 100644
index 00000000000..e7258254529
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-18.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-19.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
new file mode 100644
index 00000000000..c0161a1ba36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-19.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1 (op1, result, 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]+} 1 } } */
+/* { 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-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
new file mode 100644
index 00000000000..9f8ac99f294
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-2.c
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+
+  return __riscv_vfadd_vv_f32m1 (result, op2, vl);
+}
+
+/* { 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]} 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-20.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
new file mode 100644
index 00000000000..9e75b79722e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-20.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 2, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, result, 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]+} 5 } } */
+/* { 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-21.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
new file mode 100644
index 00000000000..aec56427371
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-21.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 2, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, result, 3, 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]+} 5 } } */
+/* { 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]} 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-22.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
new file mode 100644
index 00000000000..83bc26a8d78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-22.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1_rm(op1, result, 4, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, 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]+} 3 } } */
+/* { 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]} 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-23.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
new file mode 100644
index 00000000000..e7c51ea874e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-23.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+  else
+    result = __riscv_vfadd_vv_f32m1_rm(op2, 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]+} 3 } } */
+/* { 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-24.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
new file mode 100644
index 00000000000..46ac8e02215
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-24.c
@@ -0,0 +1,13 @@ 
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t *out, vfloat32m1_t op1, size_t vl)
+{
+}
+
+/* { 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-25.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
new file mode 100644
index 00000000000..b70f531a24c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-25.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op2, result, 3, vl);
+      *(vfloat32m1_t *) out = 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]+} 1 } } */
+/* { 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-26.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
new file mode 100644
index 00000000000..78b2946b9fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-26.c
@@ -0,0 +1,23 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = 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 {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-27.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
new file mode 100644
index 00000000000..4dba68040e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-27.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1 (op2, result, vl);
+      *(vfloat32m1_t *) (out + 16) = 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-not {frrm\s+[axs][0-9]+} } } */
+/* { 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]+} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
new file mode 100644
index 00000000000..35a37b83239
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-28.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+                              float *out)
+{
+  vfloat32m1_t result = op1;
+
+  result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+  else
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op2, result, 3, vl);
+      *(vfloat32m1_t *) (out + 16) = 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]+} 1 } } */
+/* { 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-29.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
new file mode 100644
index 00000000000..e24c2045f43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-29.c
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (float *in, float *out, int n, size_t vl)
+{
+  for (int i = 0; i < n; i++)
+    {
+      vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i, vl);
+      vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 4, vl);
+      __riscv_vse32_v_f32m1 (out + i, result, vl);
+    }
+
+  for (int i = 0; i < n; i++)
+    {
+      vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 100, vl);
+      vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+      __riscv_vse32_v_f32m1 (out + i + 100, result, vl);
+    }
+}
+
+/* { 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-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
new file mode 100644
index 00000000000..600ac45bb03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-3.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, 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 {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-30.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
new file mode 100644
index 00000000000..bf5772073f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-30.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (float *in, float *out, int n, int cond, size_t vl)
+{
+  for (int i = 0; i < n; i++)
+    {
+      if (cond)
+        {
+          vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 100, vl);
+          vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+          __riscv_vse32_v_f32m1 (out + i + 100, result, vl);
+        }
+      else
+        {
+          vfloat32m1_t v = __riscv_vle32_v_f32m1 (in + i + 200, vl);
+          vfloat32m1_t result = __riscv_vfadd_vv_f32m1_rm (v, v, 3, vl);
+          __riscv_vse32_v_f32m1 (out + i + 200, result, vl);
+        }
+    }
+}
+
+/* { 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]} 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-31.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
new file mode 100644
index 00000000000..64a0c8cd2b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-31.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+void
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
+			      int n, float *out)
+{
+  vfloat32m1_t result = __riscv_vfadd_vv_f32m1 (op1, op2, vl);
+
+  if (vl % 4 == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (op1, result, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+
+  if (n > 0)
+    {
+      result = __riscv_vfadd_vv_f32m1 (op2, result, vl);
+      *(vfloat32m1_t *) (out + 100) = 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]+} 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-32.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
new file mode 100644
index 00000000000..a24ffd799fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-32.c
@@ -0,0 +1,25 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+size_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, int count,
+         size_t vl, float *out)
+{
+  vfloat32m1_t result = op1;
+
+  if (count == 0)
+    {
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 4, vl);
+      *(vfloat32m1_t *) out = result;
+    }
+
+  return vl;
+}
+
+/* { 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]+} 1 } } */
+/* { 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-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
new file mode 100644
index 00000000000..aaf912e0923
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-4.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (vl % 4 == 0)
+    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]+} 1 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 1 } } */
+/* { 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-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
new file mode 100644
index 00000000000..9149388bea1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-5.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat32m1_t
+test_float_point_dynamic_frm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
+{
+  vfloat32m1_t result = op1;
+
+  if (vl % 4 == 0)
+    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]+} 1 } } */
+/* { 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-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
new file mode 100644
index 00000000000..1541de88979
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-6.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 2, vl);
+      else
+        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]+} 1 } } */
+/* { 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-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
new file mode 100644
index 00000000000..6f24317c51a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-7.c
@@ -0,0 +1,27 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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
+        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]+} 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-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
new file mode 100644
index 00000000000..a4846b05ab6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-8.c
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1_rm (result, op2, 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]+} 3 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[asx][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 3 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[asx][0-9]+} 1 } } */
+/* { dg-final { scan-assembler-not {fsrmi\s+[asx][0-9]+,\s*[01234]} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c
new file mode 100644
index 00000000000..cfb8fca08a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-dynamic-frm-9.c
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+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, 1, vl);
+      result = __riscv_vfadd_vv_f32m1 (result, op2, 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]+} 3 } } */
+/* { 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]} 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-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
index 732e0305a3d..608b3883dd0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-1.c
@@ -28,4 +28,6 @@  test_vfadd_vf_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, float32_t op2,
 }
 
 /* { 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 {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {frrm\s+[axs][0-9]+} 4 } } */
+/* { dg-final { scan-assembler-times {fsrmi\s+[01234]} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
index c46910b878c..3252f67d078 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-10.c
@@ -20,4 +20,6 @@  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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
index 72e5d2084b3..96e10c720b8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-2.c
@@ -11,4 +11,6 @@  test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
 }
 
 /* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
index c9e8d0a6eaf..519537c07cb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-3.c
@@ -11,4 +11,6 @@  test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
 }
 
 /* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
index a288e0be628..f9e6bc36a90 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-4.c
@@ -20,4 +20,6 @@  test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
 }
 
 /* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
index bb77a6efc62..c3f6302384a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-5.c
@@ -20,4 +20,6 @@  test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
 }
 
 /* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 3 } } */
+/* { 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 {fsrmi\s+[01234]} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
index 6d896e0953e..1ef0e015d8f 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c
@@ -28,4 +28,6 @@  test_vfadd_vf_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, float32_t op2,
 }
 
 /* { 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 {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {frrm\s+[axs][0-9]+} } } */
+/* { dg-final { scan-assembler-not {fsrmi\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 7b1602fd509..12db112dd0b 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,4 +26,6 @@  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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
index 37481ddac38..cc83dae4e95 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-8.c
@@ -24,4 +24,6 @@  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]+} 1 } } */
-/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
+/* { 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 {fsrmi\s+[01234]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
index 7ae834ad531..3b650ec2948 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-9.c
@@ -21,4 +21,6 @@  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+[ax][0-9]+,\s*[ax][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 {fsrmi\s+[01234]} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
index 210c49c5e8d..245ce7d1fc0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-1.c
@@ -44,8 +44,6 @@  assert_equal (int a, int b, char *message)
 vfloat32m1_t __attribute__ ((noinline))
 test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
 {
-  set_frm (0);
-
   vfloat32m1_t result;
 
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
@@ -73,7 +71,10 @@  main ()
   vfloat32m1_t op1;
   vfloat32m1_t op2;
 
+  set_frm (4);
   test_float_point_frm_run (op1, op2, vl);
 
+  assert_equal (4, get_frm (), "The value of frm register should be 4.");
+
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
index a7036529cf2..ec4cc26135d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-2.c
@@ -44,8 +44,6 @@  assert_equal (int a, int b, char *message)
 vfloat32m1_t __attribute__ ((noinline))
 test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
 {
-  set_frm (0);
-
   vfloat32m1_t result = {};
 
   result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
@@ -64,7 +62,10 @@  main ()
   vfloat32m1_t op1 = {};
   vfloat32m1_t op2 = {};
 
+  set_frm (2);
   test_float_point_frm_run (op1, op2, vl);
 
+  assert_equal (2, get_frm (), "The value of frm register should be 2.");
+
   return 0;
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
index 6924bdf6a05..32ed6962dc9 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-run-3.c
@@ -44,17 +44,15 @@  assert_equal (int a, int b, char *message)
 vfloat32m1_t __attribute__ ((noinline))
 test_float_point_frm_run (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl)
 {
-  set_frm (0);
-
   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.");
+
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
   result = __riscv_vfadd_vv_f32m1 (op1, result, vl);
 
-  assert_equal (4, get_frm (), "The value of frm register should be 4.");
-
   return result;
 }
 
@@ -65,7 +63,10 @@  main ()
   vfloat32m1_t op1 = {};
   vfloat32m1_t op2 = {};
 
+  set_frm (0);
   test_float_point_frm_run (op1, op2, vl);
 
+  assert_equal (0, get_frm (), "The value of frm register should be 0.");
+
   return 0;
 }