We overlooked the side effects of the rounding mode in the pattern,
which can impact the result of float_extend and lead to incorrect
optimizations in the final program. This issue likely affects nearly
all similar patterns that involve rounding modes, and the tests in
this patch only highlight one example. It seems challenging to address,
and I only implemented a simple fix, which is not a good way to solve
the problem.

Any comments on this?

gcc/ChangeLog:

        * config/riscv/vector-iterators.md (UNSPEC_VRM): New.
        * config/riscv/vector.md: Use UNSPEC for float_extend.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/base/bug-11.c: New test.

Reported-by: CunJian Huang <huangcunjian.hu...@alibaba-inc.com>
Signed-off-by: Jin Ma <ji...@linux.alibaba.com>
---
 gcc/config/riscv/vector-iterators.md          |  3 +++
 gcc/config/riscv/vector.md                    |  6 +++--
 .../gcc.target/riscv/rvv/base/bug-11.c        | 24 +++++++++++++++++++
 3 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/bug-11.c

diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index c1bd7397441..bd592f736e2 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -120,6 +120,9 @@ (define_c_enum "unspec" [
 
   UNSPEC_SF_VFNRCLIP
   UNSPEC_SF_VFNRCLIPU
+
+  ;; Side effects of rounding mode
+  UNSPEC_VRM
 ])
 
 (define_c_enum "unspecv" [
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 8ee43cf0ce1..e971dcdc973 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -7135,8 +7135,10 @@ (define_insn 
"@pred_single_widen_<plus_minus:optab><mode>_scalar"
          (plus_minus:VWEXTF
            (match_operand:VWEXTF 3 "register_operand"            " vr, vr, vr, 
vr")
            (float_extend:VWEXTF
-             (vec_duplicate:<V_DOUBLE_TRUNC>
-               (match_operand:<VSUBEL> 4 "register_operand"      "  f,  f,  f, 
 f"))))
+             (unspec:VWEXTF
+               [(vec_duplicate:<V_DOUBLE_TRUNC>
+                 (match_operand:<VSUBEL> 4 "register_operand"      "  f,  f,  
f,  f"))
+                 (reg:SI FRM_REGNUM)] UNSPEC_VRM)))
          (match_operand:VWEXTF 2 "vector_merge_operand"          " vu,  0, vu, 
 0")))]
   "TARGET_VECTOR"
   "vfw<insn>.wf\t%0,%3,%4%p1"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/bug-11.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/bug-11.c
new file mode 100644
index 00000000000..52d940cb57a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/bug-11.c
@@ -0,0 +1,24 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64d -O2" } */
+
+#include <riscv_vector.h>
+
+int main ()
+{
+  float data_store = 0;
+  int8_t mask = 1;
+  size_t vl = 1;
+  float data_load = 0.0;
+  _Float16 data_sub = 0.0;
+  vint8mf8_t mask_value = __riscv_vle8_v_i8mf8 (&mask, vl);
+  vbool64_t vmask = __riscv_vmseq_vx_i8mf8_b64 (mask_value, 1, vl);
+  vfloat32mf2_t vd_load = __riscv_vfmv_v_f_f32mf2 (0, __riscv_vsetvlmax_e32mf2 
());
+  vfloat32mf2_t vreg_memory = __riscv_vle32_v_f32mf2_tu (vd_load, &data_load, 
vl);
+  vfloat32mf2_t vreg = __riscv_vfwsub_wf_f32mf2_rm_tum (vmask, vreg_memory, 
vreg_memory, data_sub, __RISCV_FRM_RDN, vl);
+  __riscv_vse32_v_f32mf2 (&data_store, vreg, vl);
+
+  __builtin_printf ("%f\n", data_store);
+  return 0;
+}
+
+/* { dg-output "-0.000000\\s+\n" } */
-- 
2.25.1

Reply via email to