RE: [PATCH 1/1] aarch64: Improve pfirst and brk* intrinsic folding
Tamar Christina <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <VI0PR08MB10392A05586602291F63B06C6FFA72@VI0PR08MB10392.eurprd08.prod.outlook.com> |
Hi Dylan, > -----Original Message----- > From: Dylan Rees <[email protected]> > Sent: 10 August 2026 14:36 > To: [email protected] > Cc: Dylan Rees <[email protected]>; [email protected]; > [email protected]; Tamar Christina <[email protected]> > Subject: [PATCH 1/1] 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. > --- > .../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); You can use tree pg = f.gp_value (f.call); to simplify this as the function already knows where the gp is. > + if ((f.pred == PRED_z || f.pred == PRED_m) > + && is_ptrue (pg, f.type_suffix (0).element_bytes)) > + { And then pn can be extracted only where needed tree pn = gimple_call_arg (f.call, f.gp_index + 1); > + 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 ()); I think it's clearer written out. So If (m_unspec == ..) return f.fold_to_.. return f.fold_to_ Patch is OK with those changes. Thanks, Tamar > + 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