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