On Thu, Jul 30, 2026 at 8:54 AM Tamar Christina <[email protected]> wrote: > > Hi Pengxuan, > > > > I’m very sorry for the delay here. This slipped through the cracks.
It is ok; things happen. Prengxuan has been moved over to work on a different project now. I will have someone else work on this. > > > > I don’t think this optimization is in general optimal as it depends whether > the shuffle is in a loop or not. > > When in a loop the literal load is pulled out of the loop so you only pay for > it once. > > > > Within the loop this would change the permute for 2 to 4 cycles. That is what I thought too. I was worried about that but I see LLVM does this without any concern for that (I think). > > > > I think to do this the optimization has to be moved to RTL, where you can use > a helper similar to aarch64_split_simd_shift_p to check if the instruction > executes less often than the function entry point which > > gives us a decent indication if we’re in a loop or not. > > > > In RTL you can detect the permute sequence similarly to vect_par_cnst_hi_half > so I think a split here makes more > > sense. Thanks, Andrea > > > > Thanks, > > Tamar > > > > From: Pengxuan Zheng <[email protected]> > Sent: 13 May 2026 21:45 > To: [email protected] > Subject: Re: [PATCH] aarch64: Recognize vector permute patterns which can be > optimized as REV64+EXT [PR102055] > > > > Gentle ping > > > > On Fri, Apr 17, 2026 at 11:40 AM Pengxuan Zheng > <[email protected]> wrote: > > 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. > > PR target/102055 > > gcc/ChangeLog: > > * config/aarch64/aarch64.cc (aarch64_evpc_rev64_ext): New. > (aarch64_expand_vec_perm_const_1): Call aarch64_evpc_rev64_ext. > > gcc/testsuite/ChangeLog: > > * gcc.target/aarch64/pr102055.c: New test. > > Signed-off-by: Pengxuan Zheng <[email protected]> > --- > gcc/config/aarch64/aarch64.cc | 32 ++++++++++++++++ > gcc/testsuite/gcc.target/aarch64/pr102055.c | 42 +++++++++++++++++++++ > 2 files changed, 74 insertions(+) > 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 62194b96450..5fdb1a42c99 100644 > --- a/gcc/config/aarch64/aarch64.cc > +++ b/gcc/config/aarch64/aarch64.cc > @@ -27714,6 +27714,36 @@ aarch64_evpc_rev_global (struct expand_vec_perm_d *d) > return true; > } > > +/* 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 (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) > { > @@ -28175,6 +28205,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.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
