https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119832
Bug ID: 119832 Summary: RISC-V: Redundant floating point rounding mode store/restore Product: gcc Version: unknown Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: kito at gcc dot gnu.org Target Milestone: --- Target: riscv How to reproduce: ```shell $ riscv64-unknown-linux-gnu-gcc test.cc -S -O3 -march=rv64gcv -ffast-math ``` Testcase: ```c++ 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(); } } ``` Generated asm (simplified): ```asm _Z2akP2aei: ... frrm a5 ... fsrm a5 ; No one really change a5 any where, ; and no static rounding mode instruction at all ... ... frrm a5 ``` Symptom: There is no static rounding mode in the function, but we still decide back up and restore the floating point rounding mode register, we could drop the back up and restore instruction in theory. Why: There is a basic block has two in edge, one with FRM_DYN_CALL and and one with FRM_DYN, it made the gcc feel the mode is unknown status so become FRM_NONE. And it seems like because there is some abnormal edge that disturb some thing... Possible Solution: I found a target hook called TARGET_MODE_CONFLUENCE, that can merge two different mode and return a merged mode, that seems can resolve this issue, but not sure if it's right direction.