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

Reply via email to