[gcc r17-3390] aarch64: Improve pfirst and brk* intrinsic folding

Pengfei Li via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:61d1f4da2ff8450e6d7211914444537d9a27d452

commit r17-3390-g61d1f4da2ff8450e6d7211914444537d9a27d452
Author: Dylan Rees <[email protected]>
Date:   Mon Aug 17 13:35:22 2026 +0000

    aarch64: Improve pfirst and brk* intrinsic folding
    
    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.

Diff:
---
 gcc/config/aarch64/aarch64-sve-builtins-base.cc    |  31 ++++
 .../gcc.target/aarch64/sve/acle/general/pfirst_2.c |  67 ++++++++
 .../gcc.target/aarch64/sve/pr121604_brk.c          | 169 +++++++++++++++++++--
 3 files changed, 257 insertions(+), 10 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index 5d01d875a9da..bad2ccb2fd6e 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -346,6 +346,26 @@ class svbrk_unary_impl : public function_base
 public:
   constexpr svbrk_unary_impl (unspec unspec) : m_unspec (unspec) {}
 
+  gimple *
+  fold (gimple_folder &f) const override
+  {
+    tree pg = f.gp_value (f.call);
+    if ((f.pred == PRED_z || f.pred == PRED_m)
+	&& is_ptrue (pg, f.type_suffix (0).element_bytes))
+      {
+	tree pn = gimple_call_arg (f.call, f.gp_index + 1);
+	if (is_pfalse (pn))
+	  return f.fold_to_ptrue ();
+	if (is_ptrue (pn, f.type_suffix (0).element_bytes))
+	  {
+	    if (m_unspec == UNSPEC_BRKA)
+	      return f.fold_to_vl_pred (1);
+	    return f.fold_to_pfalse ();
+	  }
+      }
+    return nullptr;
+  }
+
   rtx
   expand (function_expander &e) const override
   {
@@ -2565,6 +2585,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 000000000000..3fba71c4cd0f
--- /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 a474a20554d3..ccb28d748335 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.