[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