]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Disable shrink-wrap for locally-streaming functions [PR 123624]
authorAlice Carlotti <alice.carlotti@arm.com>
Wed, 14 Jan 2026 13:48:35 +0000 (13:48 +0000)
committerAlice Carlotti <alice.carlotti@arm.com>
Tue, 10 Feb 2026 16:42:06 +0000 (16:42 +0000)
The meaning of poly_int values changes depending on whether we are in
streaming or non-streaming mode, but this dependency is not explicitly
tracked.  Locally-streaming functions can change streaming state in the
prologue and epilogue, so it is unsafe to apply shrink wrapping to these
functions, as doing so could change the mode seen by instructions like
cntd.

gcc/ChangeLog:

PR target/123624
* config/aarch64/aarch64-protos.h
(aarch64_use_simple_return_insn_p): New.
* config/aarch64/aarch64.cc
(aarch64_use_simple_return_insn_p): New, used...
* config/aarch64/aarch64.md (simple_return): ...here.

gcc/testsuite/ChangeLog:

PR target/123624
* gcc.target/aarch64/sme/sme-shrinkwrap.c: New test.

gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/sme/sme-shrinkwrap.c [new file with mode: 0644]

index 48d3a3de2356d385fc9612b5a0c546623bbc60fe..d1f2873f208bba675aab82dcf2831da3350785c6 100644 (file)
@@ -984,6 +984,7 @@ bool aarch64_uimm12_shift (unsigned HOST_WIDE_INT);
 int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &);
 bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT);
 bool aarch64_use_return_insn_p (void);
+bool aarch64_use_simple_return_insn_p (void);
 const char *aarch64_output_casesi (rtx *);
 const char *aarch64_output_load_tp (rtx);
 const char *aarch64_output_sme_zero_za (rtx);
index 57aa83de3fbfea8f0f70f509d903c36c084114b3..00e619f26c5f2832dce3a4d99cb405872e78df5f 100644 (file)
@@ -10794,6 +10794,20 @@ aarch64_use_return_insn_p (void)
   return known_eq (cfun->machine->frame.frame_size, 0);
 }
 
+/* Return false for locally streaming functions in order to avoid
+   shrink-wrapping them.  Shrink-wrapping is unsafe when the function prologue
+   and epilogue contain streaming state change, because these implicitly change
+   the meaning of poly_int values.  */
+
+bool
+aarch64_use_simple_return_insn_p (void)
+{
+  if (aarch64_cfun_enables_pstate_sm ())
+    return false;
+
+  return true;
+}
+
 /* Generate the epilogue instructions for returning from a function.
    This is almost exactly the reverse of the prolog sequence, except
    that we need to insert barriers to avoid scheduling loads that read
index 70a64a6c0ed865f368430e6529ccc823d709cd5a..e44b1cd9eefa7a81f16c2111562f355e5b9234c0 100644 (file)
 
 (define_insn "simple_return"
   [(simple_return)]
-  ""
+  "aarch64_use_simple_return_insn_p ()"
   {
     output_asm_insn ("ret", operands);
     return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sme-shrinkwrap.c b/gcc/testsuite/gcc.target/aarch64/sme/sme-shrinkwrap.c
new file mode 100644 (file)
index 0000000..b8dfd5f
--- /dev/null
@@ -0,0 +1,78 @@
+/* { dg-options "-O3 -fshrink-wrap" } */
+/* { dg-do run { target { aarch64_sme_hw && aarch64_sve_hw } } } */
+/* { dg-do compile { target { ! { aarch64_sme_hw && aarch64_sve_hw } } } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sme.h>
+
+#pragma GCC target "+sve"
+
+[[gnu::noipa]]
+__arm_streaming
+int callee (int x)
+{
+  return 0;
+}
+
+/*
+** foo:
+**     cbnz    w0, [^\n]*
+**     cntd    x0
+**     ret
+**     ...
+*/
+__arm_streaming
+int foo(int x)
+{
+    if (x)
+        return callee(3);
+    return svcntd();
+}
+
+/*
+** bar:
+**     ...
+**     smstart [^\n]*
+**     ...
+** (
+**     cntd    [^\n]*
+**     ...
+**     cbn?z   [^\n]*
+** |
+**     cbn?z   [^\n]*
+**     ...
+**     cntd    [^\n]*
+** )
+**     ...
+*/
+
+__arm_locally_streaming
+int bar(int x)
+{
+    if (x)
+        return callee(3);
+    return svcntd();
+}
+
+/*
+** baz:
+**     cbnz    w0, [^\n]*
+**     cntd    x0
+**     ret
+**     ...
+*/
+__arm_streaming
+int baz(int x)
+{
+    if (x)
+        return callee(3);
+    return svcntd();
+}
+
+[[gnu::noipa]]
+int main()
+{
+  if (bar(0) != svcntsd())
+    __builtin_abort();
+  return 0;
+}