]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Fix sibcalls involving shared-ZT0 functions
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Feb 2024 11:12:28 +0000 (11:12 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Feb 2024 11:12:28 +0000 (11:12 +0000)
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.

gcc/config/aarch64/aarch64.cc
gcc/testsuite/gcc.target/aarch64/sme/sibcall_9.c [new file with mode: 0644]

index de746e28ca5a26a4e45c2be8f7b315d0d9285f5f..f9cedd31bc1bc7f5e95e24a24b14ab06bdc7709b 100644 (file)
@@ -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 (file)
index 0000000..2e133c8
--- /dev/null
@@ -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(); }