https://gcc.gnu.org/g:9e71740a62d74b212bdafd930142d069de32fb45

commit 9e71740a62d74b212bdafd930142d069de32fb45
Author: Jim Lin <[email protected]>
Date:   Fri Sep 19 07:08:09 2025 -0600

    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.
    
    (cherry picked from commit afdf44154fd2b54f9f8b6055fae800d4fce7f05c)

Diff:
---
 gcc/config/riscv/riscv.cc                          |  9 +---
 gcc/testsuite/gcc.target/riscv/pr120811.c          | 42 ++++++++++++++++++
 .../gcc.target/riscv/save-restore-cfi-3.c          | 16 +++++++
 libgcc/config/riscv/save-restore.S                 | 50 ++++++++++++++++++----
 4 files changed, 101 insertions(+), 16 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 228571f2b3f5..cf1b5d400167 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 000000000000..c28e5ec4cc36
--- /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 000000000000..3d35ad185f77
--- /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 fc654472a4c5..f6519e35e375 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

Reply via email to