On Thu, Aug 27, 2026 at 12:51 PM Tamar Christina <[email protected]> wrote:
> Hi Pengxuan, > > > -----Original Message----- > > From: Pengxuan Zheng <[email protected]> > > Sent: 27 August 2026 03:03 > > To: [email protected] > > Subject: [PATCH v2] aarch64: Recognize vector permute patterns which can > be > > optimized as REV64+EXT [PR102055] > > > > Currently, with Advanced SIMD > > > > vector char > > f (vector char a) > > { > > return __builtin_shuffle (a, (vector char){ 15, 14, 13, 12, 11, 10, 9, > 8, > > 7, 6, 5, 4, 3, 2, 1, 0 }); > > } > > > > generates: > > > > f: > > adrp x0, .LANCHOR0 > > ldr q31, [x0, #:lo12:.LANCHOR0] > > tbl v0.16b, {v0.16b}, v31.16b > > ret > > .set .LANCHOR0,. + 0 > > .LC0: > > .byte 15 > > .byte 14 > > .byte 13 > > .byte 12 > > .byte 11 > > .byte 10 > > .byte 9 > > .byte 8 > > .byte 7 > > .byte 6 > > .byte 5 > > .byte 4 > > .byte 3 > > .byte 2 > > .byte 1 > > .byte 0 > > > > With this patch, it generates REV64 followed by EXT: > > > > f: > > rev64 v0.16b, v0.16b > > ext v0.16b, v0.16b, v0.16b, #8 > > ret > > > > Bootstrapped and tested on aarch64_linux_gnu. > > > > Changes since v1: > > * v2: Add loop check to avoid generating REV64+EXT if the shuffle is > inside a > > loop. > > > > PR target/102055 > > > > gcc/ChangeLog: > > > > * config/aarch64/aarch64.cc (is_bb_in_loop): New. > > (aarch64_evpc_rev64_ext): New. > > (aarch64_expand_vec_perm_const_1): Call aarch64_evpc_rev64_ext. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/aarch64/pr102055-loop.c: New test. > > * gcc.target/aarch64/pr102055.c: New test. > > > > Signed-off-by: Pengxuan Zheng <[email protected]> > > --- > > gcc/config/aarch64/aarch64.cc | 44 +++++++++++++++++++ > > .../gcc.target/aarch64/pr102055-loop.c | 16 +++++++ > > gcc/testsuite/gcc.target/aarch64/pr102055.c | 42 ++++++++++++++++++ > > 3 files changed, 102 insertions(+) > > create mode 100644 gcc/testsuite/gcc.target/aarch64/pr102055-loop.c > > create mode 100644 gcc/testsuite/gcc.target/aarch64/pr102055.c > > > > diff --git a/gcc/config/aarch64/aarch64.cc > b/gcc/config/aarch64/aarch64.cc > > index ec9fe25e9cc..081fc381713 100644 > > --- a/gcc/config/aarch64/aarch64.cc > > +++ b/gcc/config/aarch64/aarch64.cc > > @@ -28394,6 +28394,48 @@ aarch64_evpc_rev_global (struct > > expand_vec_perm_d *d) > > return true; > > } > > > > +static bool > > +is_bb_in_loop (basic_block bb) > > +{ > > + if (!bb || !cfun || !cfun->curr_properties) > > + return false; > > + > > + return bb_loop_depth (bb) > 0; > > +} > > I don't think the cfun checks are needed, does > return bb && bb_loop_depth (bb) > 0; work or did I miss a reason for > checking > cfun? > > Also could you mark this function with inline. > > The patch is OK with these changes. > Yes, the cfun checks are not needed. I've removed the cfun checks and marked the function inline. Pushed the patch as r17-3712-g4182cf11e. Thanks again for the review! Thanks, Pengxuan > > Thanks, > Tamar > > > + > > +/* Recognize patterns for the Advanced SIMD REV64 + EXT insns, which > > reverse > > + elements within a full vector. */ > > + > > +static bool > > +aarch64_evpc_rev64_ext (struct expand_vec_perm_d *d) > > +{ > > + poly_uint64 nelt = d->perm.length (); > > + > > + if (!d->one_vector_p || d->vec_flags != VEC_ADVSIMD) > > + return false; > > + > > + if (!d->perm.series_p (0, 1, nelt - 1, -1)) > > + return false; > > + > > + if (is_bb_in_loop (gimple_bb (currently_expanding_gimple_stmt))) > > + return false; > > + > > + if (d->testing_p) > > + return true; > > + > > + rtx tmp1 = gen_reg_rtx (d->vmode); > > + rtx tmp2 = gen_reg_rtx (V16QImode); > > + rtx unspec_rev64 > > + = gen_rtx_UNSPEC (d->vmode, gen_rtvec (1, d->op0), UNSPEC_REV64); > > + emit_set_insn (tmp1, unspec_rev64); > > + rtvec vec = gen_rtvec (3, gen_lowpart (V16QImode, tmp1), > > + gen_lowpart (V16QImode, tmp1), GEN_INT (8)); > > + rtx unspec_ext = gen_rtx_UNSPEC (V16QImode, vec, UNSPEC_EXT); > > + emit_set_insn (tmp2, unspec_ext); > > + emit_set_insn (d->target, gen_lowpart (d->vmode, tmp2)); > > + return true; > > +} > > + > > static bool > > aarch64_evpc_dup (struct expand_vec_perm_d *d) > > { > > @@ -28858,6 +28900,8 @@ aarch64_expand_vec_perm_const_1 (struct > > expand_vec_perm_d *d) > > return true; > > else if (aarch64_evpc_hvla (d)) > > return true; > > + else if (aarch64_evpc_rev64_ext (d)) > > + return true; > > else if (aarch64_evpc_reencode (d)) > > return true; > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr102055-loop.c > > b/gcc/testsuite/gcc.target/aarch64/pr102055-loop.c > > new file mode 100644 > > index 00000000000..26ec52e37d7 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/aarch64/pr102055-loop.c > > @@ -0,0 +1,16 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2" } */ > > + > > +/* Check that the shuffle is NOT optimized to rev64+ext inside a loop. > */ > > +/* { dg-final { scan-assembler-not "rev64" } } */ > > + > > +#define vector __attribute__ ((vector_size (16))) > > + > > +void > > +f (vector char *dst, vector char *src, int n) > > +{ > > + for (int i = 0; i < n; i++) > > + dst[i] > > + = __builtin_shuffle (src[i], (vector char) {15, 14, 13, 12, 11, > 10, 9, 8, > > + 7, 6, 5, 4, 3, 2, 1, 0}); > > +} > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr102055.c > > b/gcc/testsuite/gcc.target/aarch64/pr102055.c > > new file mode 100644 > > index 00000000000..39b6355fc66 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/aarch64/pr102055.c > > @@ -0,0 +1,42 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2" } */ > > +/* { dg-final { check-function-bodies "**" "" "" } } */ > > + > > +#define vector __attribute__ ((vector_size (16))) > > + > > +/* > > +** f: > > +** rev64 v([0-9]+).16b, v0.16b > > +** ext v0.16b, v\1.16b, v\1.16b, #8 > > +** ret > > +*/ > > +vector char > > +f (vector char a) > > +{ > > + return __builtin_shuffle (a, (vector char){ 15, 14, 13, 12, 11, 10, > 9, 8, > > + 7, 6, 5, 4, 3, 2, 1, 0 }); > > +} > > + > > +/* > > +** f1: > > +** rev64 v([0-9]+).8h, v0.8h > > +** ext v0.16b, v\1.16b, v\1.16b, #8 > > +** ret > > +*/ > > +vector short > > +f1 (vector short a) > > +{ > > + return __builtin_shuffle (a, (vector short){ 7, 6, 5, 4, 3, 2, 1, 0 > }); > > +} > > + > > +/* > > +** f2: > > +** rev64 v([0-9]+).4s, v0.4s > > +** ext v0.16b, v\1.16b, v\1.16b, #8 > > +** ret > > +*/ > > +vector int > > +f2 (vector int a) > > +{ > > + return __builtin_shuffle (a, (vector int){ 3, 2, 1, 0 }); > > +} > > -- > > 2.34.1 > >
