https://gcc.gnu.org/g:0de5c20b72a738782e31acce771c6f2085e1014b

commit r15-6703-g0de5c20b72a738782e31acce771c6f2085e1014b
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Wed Jan 8 18:20:47 2025 +0000

    aarch64: Fix overly restrictive sibcall check [PR107102]
    
    aarch64_function_ok_for_sibcall required the caller and callee
    to use the same PCS variant.  However, it should be enough for the
    callee to preserve at least as much register state as the caller;
    preserving more state is fine.
    
    ARM_PCS_AAPCS64, ARM_PCS_SIMD, and ARM_PCS_SVE agree on what
    GPRs should be preserved.  For the others:
    
    - ARM_PCS_AAPCS64 preserves D8-D15
    - ARM_PCS_SIMD preserves Q8-Q23
    - ARM_PCS_SVE preserves Z8-Z23 + P4-P15
    
    Thus it's ok for something earlier in the list to tail call something
    later in the list.
    
    gcc/
            PR target/107102
            * config/aarch64/aarch64.cc (aarch64_function_ok_for_sibcall): Only
            reject calls with different PCSes if the callee clobbers register
            state that the caller must preserve.
    
    gcc/testsuite/
            PR target/107102
            * gcc.target/aarch64/sve/sibcall_1.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64.cc                    | 12 +++-
 gcc/testsuite/gcc.target/aarch64/sve/sibcall_1.c | 80 ++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 3e700ed41e97..78d2cc4bbe49 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -6591,7 +6591,17 @@ aarch64_split_sve_subreg_move (rtx dest, rtx ptrue, rtx 
src)
 static bool
 aarch64_function_ok_for_sibcall (tree, tree exp)
 {
-  if (crtl->abi->id () != expr_callee_abi (exp).id ())
+  auto from_abi = crtl->abi->id ();
+  auto to_abi = expr_callee_abi (exp).id ();
+
+  /* ARM_PCS_SVE preserves strictly more than ARM_PCS_SIMD, which in
+     turn preserves strictly more than the base PCS.  The callee must
+     preserve everything that the caller is required to preserve.  */
+  if (from_abi != to_abi && to_abi == ARM_PCS_SVE)
+    to_abi = ARM_PCS_SIMD;
+  if (from_abi != to_abi && to_abi == ARM_PCS_SIMD)
+    to_abi = ARM_PCS_AAPCS64;
+  if (from_abi != to_abi)
     return false;
 
   tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/sibcall_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve/sibcall_1.c
new file mode 100644
index 000000000000..a54c107998eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/sibcall_1.c
@@ -0,0 +1,80 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+#define SIMD [[gnu::aarch64_vector_pcs]]
+
+void callee_base (void);
+void callee_simd (void) SIMD;
+void callee_sve (__SVBool_t);
+
+/*
+** base_to_base:
+**     b       callee_base
+*/
+void base_to_base (void) { return callee_base (); }
+
+/*
+** base_to_simd:
+**     b       callee_simd
+*/
+void base_to_simd (void) { return callee_simd (); }
+
+/*
+** base_to_sve:
+**     ldr     p0, \[x0\]
+**     b       callee_sve
+*/
+void base_to_sve (__SVBool_t *ptr) { return callee_sve (*ptr); }
+
+/*
+** simd_to_base:
+**     stp     x29, x30, [^\n]+
+**     ...
+**     bl      callee_base
+**     ...
+**     ldp     x29, x30, [^\n]+
+**     ret
+*/
+void simd_to_base (void) SIMD { return callee_base (); }
+
+/*
+** simd_to_simd:
+**     b       callee_simd
+*/
+void simd_to_simd (void) SIMD { return callee_simd (); }
+
+/*
+** simd_to_sve:
+**     ldr     p0, \[x0\]
+**     b       callee_sve
+*/
+void simd_to_sve (__SVBool_t *ptr) SIMD { return callee_sve (*ptr); }
+
+/*
+** sve_to_base:
+**     stp     x29, x30, [^\n]+
+**     ...
+**     bl      callee_base
+**     ...
+**     ldp     x29, x30, [^\n]+
+**     ret
+*/
+void sve_to_base (__SVBool_t pg) { return callee_base (); }
+
+/*
+** sve_to_simd:
+**     stp     x29, x30, [^\n]+
+**     ...
+**     bl      callee_simd
+**     ...
+**     ldp     x29, x30, [^\n]+
+**     ret
+*/
+void sve_to_simd (__SVBool_t pg) { return callee_simd (); }
+
+/*
+** sve_to_sve:
+**     b       callee_sve
+*/
+void sve_to_sve (__SVBool_t pg) { return callee_sve (pg); }

Reply via email to