https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89967

Rajeev Gadgil <gadgilrajeev at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |gadgilrajeev at gmail dot com

--- Comment #12 from Rajeev Gadgil <gadgilrajeev at gmail dot com> ---
This still reproduces on GCC 16.2.0 and on trunk 453e99a9d (2026-10-24)
with a real-world case: XNNPACK's 4x16c8 I8MM GEMM micro-kernel
(qs8-qc8w-gemm-4x16c8-minmax-fp32-neoni8mm.c). It loads activations with
vld2q_lane_u64 into two loop-carried uint64x2x2_t. Inner loop at
-O3 -march=armv8.2-a+i8mm:

                      inner-loop insns  [sp] ld/st  vector movs
  GCC 11                            70            0           18
  GCC 12                            67            3            5
  GCC 14                            62            3            2
  GCC 16.2                          64            2           11
  trunk                             63            2           10
  clang 14                          48            0            0

On Graviton4 (Neoverse-V2), XNNPACK master built with GCC 15.2 is about 2x
slower on this kernel than with clang 18/21/23, and about 1.4x slower on
mobilenet_v2's qs8 convolutions. -fstack-reuse=none and -mearly-ra=all make
no difference.

At ESRA the tuple has been scalarized (va01$val$0 / va01$val$1 PHIs). Before
each __builtin_aarch64_ld2_lanev2di_usus it is rebuilt
(va01.val[0] = ..; va01.val[1] = ..), and after each call it is split
again.

I've posted an RFC patch to gcc-patches:
https://gcc.gnu.org/pipermail/gcc-patches/2026-October/736055.html

The patch disqualifies such a tuple from SRA when it is passed whole as a
call argument inside a loop. Tuples that are only accessed element-wise in
the loop are still scalarized; excluding all vector tuples regresses
gcc.target/aarch64/pr109078.c. With the patch:
  - XNNPACK kernel inner loop: 63 -> 51 insns, no spills, no vector movs
  - the comment 0 testcase at -O2: 15 -> 3 vector movs. The 3 left are
    the zero-initialisation outside the loop; the loop itself is 8
    back-to-back ld2 with no copies.
Bootstrapped and regtested on aarch64-linux-gnu with no new failures. The
patch was written with AI assistance (it carries an Assisted-by: tag),
which is why it is posted as an RFC under the GCC AI policy.

What remains is the RA side from comment 1. For a minimal loop-carried tuple
(v = vld2q_lane (a, v, 0); v = vld2q_lane (b, v, 1); then uses of v.val[]),
expand is clean (r112 = ld2_lane (r114); r113 = ld2_lane (r112);
r114 = r113), but IRA/LRA still don't tie the V2x2DI pseudos, so a pair of
moves remains around each ld2.

Reply via email to