aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2024-02-21 11:12:28 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2024-02-21 11:12:28 +0000
commit6d56f590483b17c538e332097807a6c5a9225ea3 (patch)
tree6d493b28a871842e2769106da45718980bffe875
parent22f0cf36ec0ad4ec76b50cd87eaab925bda74df8 (diff)
downloadgcc-6d56f590483b17c538e332097807a6c5a9225ea3.zip
gcc-6d56f590483b17c538e332097807a6c5a9225ea3.tar.gz
gcc-6d56f590483b17c538e332097807a6c5a9225ea3.tar.bz2
aarch64: Fix sibcalls involving shared-ZT0 functions
In: void bar() __arm_inout("za"); void foo() __arm_inout("za", "zt0") { bar(); } foo cannot tail-call bar because foo needs to restore ZT0 after the call. I'd forgotten to update the ok_for_sibcall rules to handle this when adding SME2. Thanks to Sander de Smalen for the spot. gcc/ * config/aarch64/aarch64.cc (aarch64_function_ok_for_sibcall): Check that each individual piece of state is shared in the same way, rather than using an aggregate check for PSTATE.ZA. gcc/testsuite/ * gcc.target/aarch64/sme/sibcall_9.c: New test.
-rw-r--r--gcc/config/aarch64/aarch64.cc6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sme/sibcall_9.c51
2 files changed, 55 insertions, 2 deletions
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index de746e2..f9cedd3 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -6334,8 +6334,10 @@ aarch64_function_ok_for_sibcall (tree, tree exp)
tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
if (aarch64_fntype_pstate_sm (fntype) & ~aarch64_cfun_incoming_pstate_sm ())
return false;
- if (aarch64_fntype_pstate_za (fntype) != aarch64_cfun_incoming_pstate_za ())
- return false;
+ for (auto state : { "za", "zt0" })
+ if (bool (aarch64_cfun_shared_flags (state))
+ != bool (aarch64_fntype_shared_flags (fntype, state)))
+ return false;
return true;
}
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_9.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_9.c
new file mode 100644
index 0000000..2e133c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_9.c
@@ -0,0 +1,51 @@
+// { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" }
+// { dg-final { check-function-bodies "**" "" } }
+
+#pragma GCC target "+sme2"
+
+void gen_zt0() __arm_preserves("za") __arm_out("zt0");
+void callee() __arm_inout("za");
+
+/*
+** caller_inout:
+** ...
+** str zt0, \[[^\n]+\]
+** bl callee
+** ldr zt0, \[[^\n]+\]
+** ...
+** ret
+*/
+void caller_inout() __arm_inout("za", "zt0") { callee(); }
+
+/*
+** caller_in:
+** ...
+** str zt0, \[[^\n]+\]
+** bl callee
+** ldr zt0, \[[^\n]+\]
+** ...
+** ret
+*/
+void caller_in() __arm_inout("za") __arm_in("zt0") { callee(); }
+
+/*
+** caller_out:
+** ...
+** str zt0, \[[^\n]+\]
+** bl callee
+** ldr zt0, \[[^\n]+\]
+** ...
+** ret
+*/
+void caller_out() __arm_inout("za") __arm_in("zt0") { gen_zt0(); callee(); }
+
+/*
+** caller_preserves:
+** ...
+** str zt0, \[[^\n]+\]
+** bl callee
+** ldr zt0, \[[^\n]+\]
+** ...
+** ret
+*/
+void caller_preserves() __arm_inout("za") __arm_preserves("zt0") { callee(); }