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);
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
(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 ());
--- /dev/null
+/* { 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;
+}