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 | 37 +++++++++++++++++++++++ gcc/testsuite/g++.target/riscv/pr119832.C | 27 +++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 gcc/testsuite/g++.target/riscv/pr119832.C diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index bad59e248d0..198fe72ef68 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -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 index 00000000000..f4dc480e6d5 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/pr119832.C @@ -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" } } */ -- 2.37.1