The fold method created for 'svbrk_unary_impl' to include some new
folding cases and the expand method was amended for 'svpfirst_svpnext_impl'
to optimise a specific case. Testcase expanded for 'brk*' folding and new
testsuite added for 'pfirst' to verify behaviour.
gcc/ChangeLog:
* config/aarch64/aarch64-sve-builtins-base.cc: fold method
created for 'svbrk_unary_impl'. Cases added for folding into
'ptrue' and 'pfalse' where appropriate and not folding where
unnecessary. Expand method of 'svpfirst_svpnext_impl' extended
to handle specific case where 'ptrue' should be emitted but in
a form where it can be recognised as a flag setting operation.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/sve/pr121604_brk.c: Test extended.
* gcc.target/aarch64/sve/acle/general/pfirst_2.c: New test.
---
.../aarch64/aarch64-sve-builtins-base.cc | 29 +++
.../aarch64/sve/acle/general/pfirst_2.c | 67 +++++++
.../gcc.target/aarch64/sve/pr121604_brk.c | 169 ++++++++++++++++--
3 files changed, 255 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_2.c
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index 5d01d875a9d..b3dc6fbbdb3 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -346,6 +346,24 @@ class svbrk_unary_impl : public function_base
public:
constexpr svbrk_unary_impl (unspec unspec) : m_unspec (unspec) {}
+ gimple *
+ fold (gimple_folder &f) const override
+ {
+ unsigned int arg_offset = f.pred == PRED_m ? 1 : 0;
+ tree pg = gimple_call_arg (f.call, arg_offset);
+ tree pn = gimple_call_arg (f.call, arg_offset + 1);
+ if ((f.pred == PRED_z || f.pred == PRED_m)
+ && is_ptrue (pg, f.type_suffix (0).element_bytes))
+ {
+ if (is_ptrue (pn, f.type_suffix (0).element_bytes))
+ return (m_unspec == UNSPEC_BRKA
+ ? f.fold_to_vl_pred (1) : f.fold_to_pfalse ());
+ else if (is_pfalse (pn))
+ return f.fold_to_ptrue ();
+ }
+ return nullptr;
+ }
+
rtx
expand (function_expander &e) const override
{
@@ -2565,6 +2583,17 @@ public:
expand (function_expander &e) const override
{
machine_mode mode = e.vector_mode (0);
+ if (m_unspec == UNSPEC_PFIRST
+ && rtx_equal_p (e.args[0], CONSTM1_RTX (mode))
+ && rtx_equal_p (e.args[1], CONST0_RTX (mode)))
+ {
+ rtx pattern = gen_int_mode (AARCH64_SV_VL1, SImode);
+ rtvec vec = gen_rtvec (2, pattern, CONST0_RTX (mode));
+ rtx ptrue = gen_rtx_CONST (VNx16BImode,
+ gen_rtx_UNSPEC (VNx16BImode, vec,
+ UNSPEC_PTRUE));
+ return force_reg (VNx16BImode, ptrue);
+ }
e.add_ptrue_hint (0, mode);
return e.use_exact_insn (code_for_aarch64_sve (m_unspec, mode));
}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_2.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_2.c
new file mode 100644
index 00000000000..3fba71c4cd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_2.c
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void foo (svbool_t);
+extern void bar (svbool_t);
+
+/*
+** test1:
+** b bar
+*/
+__attribute__ ((noipa))
+void test1 (svbool_t a)
+{
+ svbool_t res = svpfirst (svpfalse (), svpfalse ());
+ if (svptest_any (res, a))
+ foo (a);
+ else
+ bar (a);
+}
+
+/*
+** test2:
+** pfalse p0\.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t test2 (svbool_t a)
+{
+ return svpfirst (svpfalse (), svpfalse ());
+}
+
+/*
+** test3:
+** ptrues p3.b, vl1
+** ...
+*/
+__attribute__ ((noipa))
+void test3 (svbool_t a)
+{
+ svbool_t res = svpfirst (svptrue_b8 (), svpfalse ());
+ if (svptest_first (svptrue_b8 (), res))
+ foo (a);
+ else
+ bar (a);
+}
+
+/*
+** test4:
+** ptrue p0.b, vl1
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t test4 (svbool_t a)
+{
+return svpfirst (svptrue_b8 (), svpfalse ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c
b/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c
index a474a20554d..ccb28d74833 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c
@@ -5,21 +5,170 @@
#include <arm_sve.h>
/*
-** foo:
-** ptrue p0\.b, all
-** brkb p0\.b, p0/z, p0\.b
+** f1m:
+** mov p0.b, p1.b
** ret
*/
-svbool_t foo () {
- return svbrkb_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ());
+__attribute__ ((noipa))
+svbool_t f1m (svbool_t a, svbool_t b)
+{
+ return svbrka_b_m (b, svpfalse_b(), a);
}
/*
-** bar:
-** ptrue p0\.b, all
-** brka p0\.b, p0/z, p0\.b
+** f1z:
+** pfalse p0.b
** ret
*/
-svbool_t bar () {
- return svbrka_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ());
+__attribute__ ((noipa))
+svbool_t f1z (svbool_t a)
+{
+ return svbrka_b_z (svpfalse_b(), a);
}
+
+/*
+** f2m:
+** ptrue p3.b, all
+** brka p1.b, p3/m, p0.b
+** mov p0.b, p1.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f2m (svbool_t a, svbool_t b)
+{
+ return svbrka_b_m (b, svptrue_b8(), a);
+}
+
+/*
+** f2z:
+** ptrue p3.b, all
+** brka p0.b, p3/z, p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f2z (svbool_t a)
+{
+ return svbrka_b_z (svptrue_b8(), a);
+}
+
+/*
+** f3z:
+** ptrue p0.b, vl1
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f3z (svbool_t a)
+{
+ return svbrka_b_z (svptrue_b8(), svptrue_b8());
+}
+
+/*
+** f3m:
+** ptrue p3.b, all
+** brka p0.b, p3/m, p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f3m (svbool_t a, svbool_t b)
+{
+ return svbrka_b_m (a, svptrue_b8(), a);
+}
+
+/*
+** f4m:
+** ptrue p0.b, vl1
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f4m (svbool_t a)
+{
+ return svbrka_b_m (a, svptrue_b8(), svptrue_b8 ());
+}
+
+/*
+** f4z:
+** ptrue p0.b, all
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t f4z ()
+{
+ return svbrka_b_z (svptrue_b8(), svpfalse());
+}
+
+/*
+** g1z:
+** pfalse p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t g1z (svbool_t a)
+{
+ return svbrkb_b_z (svpfalse_b(), a);
+}
+
+/*
+** g1m:
+** ptrue p3.b, all
+** brkb p0.b, p3/z, p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t g1m (svbool_t a)
+{
+ return svbrkb_b_m (svpfalse_b(), svptrue_b8(), a);
+}
+
+/*
+** g2z:
+** ptrue p3.b, all
+** brkb p0.b, p3/z, p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t g2z (svbool_t a)
+{
+ return svbrkb_b_z (svptrue_b8(), a);
+}
+
+/*
+** g2m:
+** ptrue p0.b, all
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t g2m (svbool_t a)
+{
+ return svbrkb_b_m (a, svptrue_b8(), svpfalse ());
+}
+
+/*
+** g3m:
+** pfalse p0.b
+** ret
+*/
+__attribute__ ((noipa))
+svbool_t g3m (svbool_t a)
+{
+ return svbrkb_b_m (a, svptrue_b8(), svptrue_b8 ());
+}
+
+int main ()
+{
+ svbool_t a = svptrue_pat_b16 (SV_VL4);
+ svbool_t b = svptrue_pat_b16 (SV_VL5);
+
+ f1m (a, b);
+ f1z (a);
+ f2m (a, b);
+ f2z (a);
+ f3m (a, b);
+ f3z (a);
+ f4m (a);
+ f4z ();
+ g1z (a);
+ g1m (a);
+ g2z (a);
+ g2m (a);
+ g3m (a);
+}
\ No newline at end of file
--
2.43.0