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
>
>

Reply via email to