https://gcc.gnu.org/g:e5d1f538bb7d2c7a7a4acf4a4516fa8933dc2888
commit r16-300-ge5d1f538bb7d2c7a7a4acf4a4516fa8933dc2888 Author: Kito Cheng <kito.ch...@sifive.com> Date: Tue Apr 29 11:35:00 2025 +0800 RISC-V: Allow different dynamic floating point mode to be merged [PR119832] 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. Diff: --- gcc/config/riscv/riscv.cc | 37 +++++++++++++++++++++++++++++++ gcc/testsuite/g++.target/riscv/pr119832.C | 27 ++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index c53e0dd7a7d1..ed635ab42f40 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 000000000000..f4dc480e6d59 --- /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" } } */