LGTM, good catch, and I am a little suppressed that we don't handle "case REG" in riscv_rtx_costs...but adding that might disturb too much at once, so this fix is fine for now, and ...and I guess we should improve that in future.
On Tue, Aug 27, 2024 at 5:19 PM Xianmiao Qu <cooper...@linux.alibaba.com> wrote: > > Currently, in RV32, even with the D extension enabled, the cost of DFmode > register moves is still set to 'COSTS_N_INSNS (2)'. This results in the > 'lower-subreg' pass splitting DFmode register moves into two SImode SUBREG > register moves, leading to the generation of many redundant instructions. > > As an example, consider the following test case: > double foo (int t, double a, double b) > { > if (t > 0) > return a; > else > return b; > } > > When compiling with -march=rv32imafdc -mabi=ilp32d, the following code is > generated: > .cfi_startproc > addi sp,sp,-32 > .cfi_def_cfa_offset 32 > fsd fa0,8(sp) > fsd fa1,16(sp) > lw a4,8(sp) > lw a5,12(sp) > lw a2,16(sp) > lw a3,20(sp) > bgt a0,zero,.L1 > mv a4,a2 > mv a5,a3 > .L1: > sw a4,24(sp) > sw a5,28(sp) > fld fa0,24(sp) > addi sp,sp,32 > .cfi_def_cfa_offset 0 > jr ra > .cfi_endproc > > After adjust the DFmode register move's cost to 'COSTS_N_INSNS (1)', the > generated code is as follows, with a significant reduction in the number > of instructions. > .cfi_startproc > ble a0,zero,.L5 > ret > .L5: > fmv.d fa0,fa1 > ret > .cfi_endproc > > gcc/ > * config/riscv/riscv.cc (riscv_rtx_costs): Optimize the cost of the > DFmode register move for RV32. > > gcc/testsuite/ > * gcc.target/riscv/rv32-movdf-cost.c: New test. > --- > gcc/config/riscv/riscv.cc | 5 +++++ > gcc/testsuite/gcc.target/riscv/rv32-movdf-cost.c | 13 +++++++++++++ > 2 files changed, 18 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/riscv/rv32-movdf-cost.c > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index 1f544c1287ec..a47dedf73c10 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -3560,6 +3560,11 @@ riscv_rtx_costs (rtx x, machine_mode mode, int > outer_code, int opno ATTRIBUTE_UN > if (outer_code == INSN > && register_operand (SET_DEST (x), GET_MODE (SET_DEST (x)))) > { > + if (REG_P (SET_SRC (x)) && TARGET_DOUBLE_FLOAT && mode == DFmode) > + { > + *total = COSTS_N_INSNS (1); > + return true; > + } > riscv_rtx_costs (SET_SRC (x), mode, outer_code, opno, total, speed); > return true; > } > diff --git a/gcc/testsuite/gcc.target/riscv/rv32-movdf-cost.c > b/gcc/testsuite/gcc.target/riscv/rv32-movdf-cost.c > new file mode 100644 > index 000000000000..cb679e7b95fb > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rv32-movdf-cost.c > @@ -0,0 +1,13 @@ > +/* { dg-do compile } */ > +/* { dg-options "-march=rv32imafdc -mabi=ilp32d" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ > + > +double foo (int t, double a, double b) > +{ > + if (t > 0) > + return a; > + else > + return b; > +} > + > +/* { dg-final { scan-assembler-not "fsd\t" } } */ > -- > 2.43.0 >