RV-Vector FP-INT insns use the rounding mode in FRM register which if
explicitly set for V insn needs, is saved/restored (although from the
psABI CC Spec, it is not clear if it actually a caller-saved or
callee-saved).

Anyhow in the failure case the save/restore were generated by the
Mode Switch pass, but then eliminated by sched1:DCE and Late-Combine.
Fix this by using unspec_volatile variant which won't be eliminated.

This showed up as SPEC2017 527.cam4 runtime aborts in glibc:round_away()
which checks for standard rounding modes and the "leaking" rounding mode
due to the bug happened to be a non-standard RISC-V specific RMM
"Round to Nearest, ties to Max".

This is testsuite clean:

|                                                        | # of unexpected case 
/ # of unique unexpected case
|                                                        |          gcc |       
   g++ |     gfortran |
| rv64imafdcv_zvl256b_zba_zbb_zbs_zicond/  lp64d/ medlow |  393 /   107 |   12 
/     4 |    7 /     2 |
| rv64imafdcv_zvl256b_zba_zbb_zbs_zicond/  lp64d/ medlow |  393 /   107 |   12 
/     4 |    7 /     2 |

        PR target/118646
        PR target/118103

gcc/ChangeLog:
        * config/riscv/riscv.cc (riscv_emit_frm_mode_set): Use volatile
        fsrmi restore.

gcc/testsuite/ChangeLog:
        * gfortran.target/riscv/rvv/pr118646.f90 (New Test).

Signed-off-by: Vineet Gupta <vine...@rivosinc.com>
---
 gcc/config/riscv/riscv.cc                     |  2 +-
 .../gfortran.target/riscv/rvv/pr118646.f90    | 44 +++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.target/riscv/rvv/pr118646.f90

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5a3a05041773..e8eb602ef5bc 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12045,7 +12045,7 @@ riscv_emit_frm_mode_set (int mode, int prev_mode)
       else if (mode == riscv_vector::FRM_DYN
        && prev_mode != riscv_vector::FRM_DYN_CALL)
        /* Restore frm value from backup when switch to DYN mode.  */
-       emit_insn (gen_fsrmsi_restore (backup_reg));
+       emit_insn (gen_fsrmsi_restore_volatile (backup_reg));
       else if (riscv_static_frm_mode_p (mode))
        /* Set frm value when switch to static mode.  */
        emit_insn (gen_fsrmsi_restore (frm));
diff --git a/gcc/testsuite/gfortran.target/riscv/rvv/pr118646.f90 
b/gcc/testsuite/gfortran.target/riscv/rvv/pr118646.f90
new file mode 100644
index 000000000000..e63800e86269
--- /dev/null
+++ b/gcc/testsuite/gfortran.target/riscv/rvv/pr118646.f90
@@ -0,0 +1,44 @@
+! Reduced from SPEC2017 527.cam4 zm_conv.F90
+
+! { dg-do run }
+! { dg-options "-march=rv64gcv_zvl256b_zba_zbb_zbs_zicond -ftree-vectorize 
-mabi=lp64d -Ofast " }
+
+module a
+  contains
+subroutine b(f)
+
+   real d(4)
+   integer e(4)
+   integer f(4)
+   real hmax(4)
+   real g(4)
+
+   integer h(4)
+   integer l(4,5)
+   do i = 1,c
+      h(i) = 0
+   end do
+   do k = j  ,1
+      do i = 1,c
+         q = g(i) + hmax(i)
+         if (k >= nint(d(i)) .and. k <= e(i) .and. q > 1.e4) then
+            f(i) = k
+         end if
+      if (k < o ) then
+            if (buoy<= 0.) then
+               l(i,h) = k
+            end if
+         end if
+      end do
+   end do
+   do n = 1,5
+      do k = 1,m
+         do i = 1,c
+            if (k > l(i,n)) then
+               p = r()
+            end if
+         end do
+      end do
+   end do
+end
+end
-- 
2.43.0

Reply via email to