[PATCH 2/2] aarch64: Remove streaming compatible mismatch override [PR124416]
Alice Carlotti <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
In theory, it is possible to inline a callee function into a caller
function with incompatible streaming state, if we can prove that the
body of the callee function will behave identically in both streaming
and non-streaming mode. Unfortunately the existing checks are far too
lenient, so this can result in ICEs or incorrect codegen.
Fixing the checks is non-trivial, so remove them.
If this functionality is to be correctly implemented in future, it would
need to include at least the following incompatibility checks:
- Code in the callee that depends upon the vector length in any way.
- A streaming compatible function called by the callee, that would be
run under a different mode after inlining.
- An always_inline function called by the callee, that can't be inlined
into the new caller.
- Intrinsics that have different architecture requirements in streaming
vs. non-streaming mode (for example, many AdvSIMD intrinsics might be
unavailable in streaming mode).
gcc/ChangeLog:
PR target/124416
* config/aarch64/aarch64.cc (AARCH64_IPA_SM_FIXED): Delete.
(aarch64_update_ipa_fn_target_info): Don't set
AARCH64_IPA_SM_FIXED.
(aarch64_can_inline_p): Remove AARCH64_IPA_SM_FIXED uses.
gcc/testsuite/ChangeLog:
PR target/124416
* gcc.target/aarch64/sme/inlining_16.c: New test.
* gcc.target/aarch64/sme/inlining_17.c: New test.
* gcc.target/aarch64/sme/inlining_18.c: New test.
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 7f4effc0901f86ca62908692a9ee35bf6a047fd4..53830308de2fc566da80237f68423a7318db4668 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -22255,11 +22255,6 @@ aarch64_tribools_ok_for_inlining_p (int caller, int callee,
/* Bit allocations for ipa_fn_summary::target_info. */
-/* Set if the function contains a stmt that relies on the function's
- choice of PSTATE.SM setting (0 for non-streaming, 1 for streaming).
- Not meaningful for streaming-compatible functions. */
-constexpr auto AARCH64_IPA_SM_FIXED = 1U << 0;
-
/* Set if the function clobbers ZA and ZT0. Not meaningful for functions that
have ZA state. */
constexpr auto AARCH64_IPA_CLOBBERS_ZA = 1U << 1;
@@ -22282,9 +22277,6 @@ aarch64_update_ipa_fn_target_info (unsigned int &info, const gimple *stmt)
{
if (auto *ga = dyn_cast<const gasm *> (stmt))
{
- /* We don't know what the asm does, so conservatively assume that
- it requires the function's current SM mode. */
- info |= AARCH64_IPA_SM_FIXED;
for (unsigned int i = 0; i < gimple_asm_nclobbers (ga); ++i)
{
tree op = gimple_asm_clobber_op (ga, i);
@@ -22295,18 +22287,6 @@ aarch64_update_ipa_fn_target_info (unsigned int &info, const gimple *stmt)
info |= AARCH64_IPA_CLOBBERS_ZT0;
}
}
- if (auto *call = dyn_cast<const gcall *> (stmt))
- {
- if (gimple_call_builtin_p (call, BUILT_IN_MD))
- {
- /* The attributes on AArch64 builtins are supposed to be accurate.
- If the function isn't marked streaming-compatible then it
- needs whichever SM mode it selects. */
- tree decl = gimple_call_fndecl (call);
- if (aarch64_fndecl_pstate_sm (decl) != 0)
- info |= AARCH64_IPA_SM_FIXED;
- }
- }
return true;
}
@@ -22362,17 +22342,11 @@ aarch64_can_inline_p (tree caller, tree callee)
/* Streaming-compatible code can be inlined into functions with any
PSTATE.SM mode. Otherwise the caller and callee must agree on
- PSTATE.SM mode, unless we can prove that the callee is naturally
- streaming-compatible with behaviour that is independent of streaming
- state. If the callee is marked as always inline, then this last
- exception doesn't apply, to ensure that error reporting is unaffected
- by differing optimisations. */
+ PSTATE.SM mode. */
auto caller_sm = (aarch64_get_isa_flags (caller_opts) & AARCH64_FL_SM_STATE);
auto callee_sm = (aarch64_get_isa_flags (callee_opts) & AARCH64_FL_SM_STATE);
- if (callee_sm
- && caller_sm != callee_sm
- && (always_inline || callee_has_property (AARCH64_IPA_SM_FIXED)))
+ if (callee_sm && caller_sm != callee_sm)
return false;
/* aarch64_function_attribute_inlinable_p prevents new-ZA and new-ZT0
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_16.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_16.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f54683e4e796dc1fba1e7b2d343755fe9b64228
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_16.c
@@ -0,0 +1,51 @@
+/* { dg-options "-O3" } */
+#include <arm_sme.h>
+
+#pragma GCC target "+sve"
+
+static inline int callee_ns (void)
+{
+ return svcntw ();
+}
+
+int caller1_s(void) __arm_streaming
+{
+ return callee_ns () + svcntw ();
+}
+
+int caller1_sc(void) __arm_streaming_compatible
+{
+ return callee_ns () + svcntw ();
+}
+
+static inline int callee_s (void) __arm_streaming
+{
+ return svcntw ();
+}
+
+int caller2_ns(void)
+{
+ return callee_s () + svcntw ();
+}
+
+int caller2_sc(void) __arm_streaming_compatible
+{
+ return callee_s () + svcntw ();
+}
+
+static inline int callee_ls (void) __arm_streaming
+{
+ return svcntw ();
+}
+
+int caller3_ns(void)
+{
+ return callee_ls () + svcntw ();
+}
+
+int caller3_sc(void) __arm_streaming_compatible
+{
+ return callee_ls () + svcntw ();
+}
+
+/* { dg-final { scan-assembler-not {cnth} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_17.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_17.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f132798c44015a318b83a8fe375aa9f17c7b2eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_17.c
@@ -0,0 +1,91 @@
+/* { dg-options "-O3" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sme.h>
+
+#pragma GCC target "+sve"
+
+int child_sc (void) __arm_streaming_compatible;
+
+
+static inline int callee_ns (void)
+{
+ return child_sc ();
+}
+
+/*
+** caller1_s:
+** ...
+** bl callee_ns
+** ...
+*/
+int caller1_s(void) __arm_streaming
+{
+ return callee_ns ();
+}
+
+/*
+** caller1_sc:
+** ...
+** bl callee_ns
+** ...
+*/
+int caller1_sc(void) __arm_streaming_compatible
+{
+ return callee_ns ();
+}
+
+static inline int callee_s (void) __arm_streaming
+{
+ return child_sc ();
+}
+
+/*
+** caller2_ns:
+** ...
+** bl callee_s
+** ...
+*/
+int caller2_ns(void)
+{
+ return callee_s ();
+}
+
+/*
+** caller2_sc:
+** ...
+** bl callee_s
+** ...
+*/
+int caller2_sc(void) __arm_streaming_compatible
+{
+ return callee_s ();
+}
+
+__arm_locally_streaming
+static inline int callee_ls (void)
+{
+ return child_sc ();
+}
+
+/*
+** caller3_ns:
+** ...
+** b callee_ls
+** ...
+*/
+int caller3_ns(void)
+{
+ return callee_ls ();
+}
+
+/*
+** caller3_sc:
+** ...
+** bl callee_ls
+** ...
+*/
+int caller3_sc(void) __arm_streaming_compatible
+{
+ return callee_ls ();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_18.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_18.c
new file mode 100644
index 0000000000000000000000000000000000000000..d967d037740f2fc989471dce99d0cbe609aaed21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_18.c
@@ -0,0 +1,100 @@
+/* { dg-options "-O3" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sme.h>
+
+#pragma GCC target "+sve"
+
+__attribute__((always_inline))
+static inline int child_ns (void)
+{
+ return svcntw ();
+}
+
+__attribute__((always_inline))
+static inline int child_s (void) __arm_streaming
+{
+ return svcntw ();
+}
+
+static inline int callee_ns (void)
+{
+ return child_ns ();
+}
+
+/*
+** caller1_s:
+** ...
+** bl callee_ns
+** ...
+*/
+int caller1_s(void) __arm_streaming
+{
+ return callee_ns ();
+}
+
+/*
+** caller1_sc:
+** ...
+** bl callee_ns
+** ...
+*/
+int caller1_sc(void) __arm_streaming_compatible
+{
+ return callee_ns ();
+}
+
+static inline int callee_s (void) __arm_streaming
+{
+ return child_s ();
+}
+
+/*
+** caller2_ns:
+** ...
+** bl callee_s
+** ...
+*/
+int caller2_ns(void)
+{
+ return callee_s ();
+}
+
+/*
+** caller2_sc:
+** ...
+** bl callee_s
+** ...
+*/
+int caller2_sc(void) __arm_streaming_compatible
+{
+ return callee_s ();
+}
+
+__arm_locally_streaming
+static inline int callee_ls (void)
+{
+ return child_s ();
+}
+
+/*
+** caller3_ns:
+** ...
+** b callee_ls
+** ...
+*/
+int caller3_ns(void)
+{
+ return callee_ls ();
+}
+
+/*
+** caller3_sc:
+** ...
+** bl callee_ls
+** ...
+*/
+int caller3_sc(void) __arm_streaming_compatible
+{
+ return callee_ls ();
+}