]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Allow different dynamic floating point mode to be merged [PR119832]
authorKito Cheng <kito.cheng@sifive.com>
Tue, 29 Apr 2025 03:35:00 +0000 (11:35 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Wed, 30 Apr 2025 09:27:21 +0000 (17:27 +0800)
Although we already try to set the mode needed to FRM_DYN after a function call,
there are still some corner cases where both FRM_DYN and FRM_DYN_CALL may appear
on incoming edges.

Therefore, we use TARGET_MODE_CONFLUENCE to tell GCC that FRM_DYN, FRM_DYN_CALL,
and FRM_DYN_EXIT modes are compatible.

gcc/ChangeLog:

PR target/119832
* config/riscv/riscv.cc (riscv_dynamic_frm_mode_p): New.
(riscv_mode_confluence): New.
(TARGET_MODE_CONFLUENCE): Define to riscv_mode_confluence.

gcc/testsuite/ChangeLog:

PR target/119832
* g++.target/riscv/pr119832.C: New test.

gcc/config/riscv/riscv.cc
gcc/testsuite/g++.target/riscv/pr119832.C [new file with mode: 0644]

index c53e0dd7a7d125f2285b30a951537f4276aca568..ed635ab42f40c8e77614635ba4e0c0682b17c3cc 100644 (file)
@@ -12273,6 +12273,41 @@ riscv_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
     }
 }
 
+/* Return TRUE if the rouding mode is dynamic.  */
+
+static bool
+riscv_dynamic_frm_mode_p (int mode)
+{
+  return mode == riscv_vector::FRM_DYN
+        || mode == riscv_vector::FRM_DYN_CALL
+        || mode == riscv_vector::FRM_DYN_EXIT;
+}
+
+/* Implement TARGET_MODE_CONFLUENCE.  */
+
+static int
+riscv_mode_confluence (int entity, int mode1, int mode2)
+{
+  switch (entity)
+    {
+    case RISCV_VXRM:
+      return VXRM_MODE_NONE;
+    case RISCV_FRM:
+      {
+       /* FRM_DYN, FRM_DYN_CALL and FRM_DYN_EXIT are all compatible.
+          Although we already try to set the mode needed to FRM_DYN after a
+          function call, there are still some corner cases where both FRM_DYN
+          and FRM_DYN_CALL may appear on incoming edges.  */
+       if (riscv_dynamic_frm_mode_p (mode1)
+           && riscv_dynamic_frm_mode_p (mode2))
+         return riscv_vector::FRM_DYN;
+       return riscv_vector::FRM_NONE;
+      }
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Return TRUE that an insn is asm.  */
 
 static bool
@@ -14356,6 +14391,8 @@ bool need_shadow_stack_push_pop_p ()
 #define TARGET_MODE_EMIT riscv_emit_mode_set
 #undef TARGET_MODE_NEEDED
 #define TARGET_MODE_NEEDED riscv_mode_needed
+#undef TARGET_MODE_CONFLUENCE
+#define TARGET_MODE_CONFLUENCE riscv_mode_confluence
 #undef TARGET_MODE_AFTER
 #define TARGET_MODE_AFTER riscv_mode_after
 #undef TARGET_MODE_ENTRY
diff --git a/gcc/testsuite/g++.target/riscv/pr119832.C b/gcc/testsuite/g++.target/riscv/pr119832.C
new file mode 100644 (file)
index 0000000..f4dc480
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcv -mabi=lp64 -ffast-math" } */
+
+struct ac  {
+  ~ac();
+  void u();
+};
+struct ae {
+  int s;
+  float *ag;
+};
+
+float c;
+
+void ak(ae *al, int n) {
+  ac d;
+  for (int i;i<n;++i) {
+    float a = 0;
+    for (long j; j < al[i].s; j++)
+      a += al[i].ag[j];
+    c = a;
+    d.u();
+  }
+}
+
+/* { dg-final { scan-assembler-not "frrm\t" } } */
+/* { dg-final { scan-assembler-not "fsrm\t" } } */