From: Jim Lin Date: Fri, 19 Sep 2025 13:08:09 +0000 (-0600) Subject: RISC-V: Only Save/Restore required registers for ILP32E/LP64E X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=afdf44154fd2b54f9f8b6055fae800d4fce7f05c;p=thirdparty%2Fgcc.git RISC-V: Only Save/Restore required registers for ILP32E/LP64E Previously the spec https://github.com/riscv-non-isa/riscv-toolchain-conventions/pull/70 has changed the save/restore routines to save/restore the registers which are really used for ILP32E/LP64 rather than always save/restore all of ra/s0/s1. I also found here that lacks the implementation for lp64e. If it's necessary I will file anothor patch for that. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_compute_frame_info): Remove the dedicated calculation for RVE. libgcc/ChangeLog: * config/riscv/save-restore.S: Only save/restore the registers which are really used for ILP32E/LP64. gcc/testsuite/ChangeLog: * gcc.target/riscv/save-restore-cfi-3.c: New test. --- diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b93103616b8..572da2d9f83 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8109,14 +8109,7 @@ riscv_compute_frame_info (void) /* Only use save/restore routines if they don't alter the stack size. */ if (riscv_stack_align (num_save_restore * UNITS_PER_WORD) == x_save_size && !riscv_avoid_save_libcall ()) - { - /* Libcall saves/restores 3 registers at once, so we need to - allocate 12 bytes for callee-saved register. */ - if (TARGET_RVE) - x_save_size = 3 * UNITS_PER_WORD; - - frame->save_libcall_adjustment = x_save_size; - } + frame->save_libcall_adjustment = x_save_size; if (!riscv_avoid_multi_push (frame)) { diff --git a/gcc/testsuite/gcc.target/riscv/pr120811.c b/gcc/testsuite/gcc.target/riscv/pr120811.c new file mode 100644 index 00000000000..c28e5ec4cc3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr120811.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fdump-rtl-reload -fdump-rtl-late_combine2" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32gc -mabi=ilp32d -fdump-rtl-reload -fdump-rtl-late_combine2" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } "-fomit-frame-pointer" } */ + +double *a, *b, *ab, *ac, *ad, *ae, *af, *c, *i, *k, *l; +int n(int *, int, int, int), d, ag, aj; +long ai, e; +double f, g, h, o, p; +int m; +void q() { + long am = n(&d, 0, 1, 0); + for (;;) + for (int j = ag; j; ++j) { + int ao = 0; + for (; ao < aj; ao++) { + long ap = ao + j; + double ar = ad[ap] = ae[ap], az; + switch (m) + case 4: { + o = (&l[ap])[2] - (&l[ap])[3] * ((char *)ap)[am] + (&l[ap])[e] + + (&l[ap])[am]; + p = (&l[ap])[ai - 1] + (&ap)[ai] * (&l[ap])[am * ai] + + (&l[ap])[ai * 3]; + az = (&b[ap])[1] + + (&b[ap])[3] * i[ap] * (&ap)[203] * ((char *)&i[ap])[ai] - + (&i[ap])[ai * 3]; + g = (&i[ap])[e] + (&i[ap])[ai]; + h = (&ab[ap])[am] * (&ab[ap])[2] - ((char *)ap)[ai] + + (&ab[ap])[ai] * (&ap)[0] * (&af[ap])[am] * (&af[ap])[e] + + (&ap)[2] + (&af[ap])[e * am] + (&af[ap])[am * 3]; + } + ar = az * f * k[ap]; + c[ap] = ar; + a[ap] = ac[ap]; + } + } +} +/* { dg-final { scan-rtl-dump-not "const_sum_of_two_s12" "reload" } } */ +/* { dg-final { scan-rtl-dump-not "const_sum_of_two_s12" "late_combine2" } } */ +/* { dg-final { scan-assembler "addi.*sp,2047\n\tl\[dw\]\t.*,1\(.*\).*" } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/save-restore-cfi-3.c b/gcc/testsuite/gcc.target/riscv/save-restore-cfi-3.c new file mode 100644 index 00000000000..3d35ad185f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/save-restore-cfi-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-g -Os -march=rv32e -mabi=ilp32e -msave-restore" } */ +/* { dg-skip-if "" { *-*-* } {"-O2" "-O1" "-O0" "-Og" "-O3" "-Oz" "-flto"} } */ +/* { dg-final { scan-assembler-times {\.cfi_offset 8, -8} 1} } */ +/* { dg-final { scan-assembler-times {\.cfi_offset 1, -4} 1} } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 8} 1} } */ +/* { dg-final { scan-assembler-times {\.cfi_restore 8} 1} } */ +/* { dg-final { scan-assembler-times {\.cfi_restore 1} 1} } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 0} 1} } */ + +int my_getint(); + +int foo(int x) +{ + return x + my_getint(); +} diff --git a/libgcc/config/riscv/save-restore.S b/libgcc/config/riscv/save-restore.S index fc654472a4c..f6519e35e37 100644 --- a/libgcc/config/riscv/save-restore.S +++ b/libgcc/config/riscv/save-restore.S @@ -298,9 +298,8 @@ FUNC_END (__riscv_restore_0) #else #ifdef __riscv_abi_rve + FUNC_BEGIN(__riscv_save_2) -FUNC_BEGIN(__riscv_save_1) -FUNC_BEGIN(__riscv_save_0) .cfi_startproc # __riscv_save_* routine use t0/x5 as return address .cfi_return_column 5 @@ -316,21 +315,56 @@ FUNC_BEGIN(__riscv_save_0) jr t0 .cfi_endproc FUNC_END(__riscv_save_2) + +FUNC_BEGIN(__riscv_save_1) + .cfi_startproc + # __riscv_save_* routine use t0/x5 as return address + .cfi_return_column 5 + addi sp, sp, -8 + .cfi_def_cfa_offset 8 + sw s0, 0(sp) + .cfi_offset 8, -8 + sw ra, 4(sp) + .cfi_offset 1, -4 + SET_LPAD + jr t0 + .cfi_endproc FUNC_END(__riscv_save_1) + +FUNC_BEGIN(__riscv_save_0) + .cfi_startproc + # __riscv_save_* routine use t0/x5 as return address + .cfi_return_column 5 + addi sp, sp, -4 + .cfi_def_cfa_offset 4 + sw ra, 0(sp) + .cfi_offset 1, -4 + SET_LPAD + jr t0 + .cfi_endproc FUNC_END(__riscv_save_0) FUNC_BEGIN(__riscv_restore_2) -FUNC_BEGIN(__riscv_restore_1) -FUNC_BEGIN(__riscv_restore_0) .cfi_startproc - .cfi_def_cfa_offset 14 + .cfi_def_cfa_offset 12 lw s1, 0(sp) .cfi_restore 9 - lw s0, 4(sp) + addi sp, sp, 4 + +FUNC_BEGIN(__riscv_restore_1) + .cfi_restore 9 + .cfi_def_cfa_offset 8 + lw s0, 0(sp) .cfi_restore 8 - lw ra, 8(sp) + addi sp, sp, 4 + +FUNC_BEGIN(__riscv_restore_0) + .cfi_restore 8 + .cfi_restore 9 + .cfi_def_cfa_offset 4 + lw ra, 0(sp) .cfi_restore 1 - addi sp, sp, 12 + addi sp, sp, 4 .cfi_def_cfa_offset 0 ret .cfi_endproc