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

--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Tamar Christina <[email protected]>:

https://gcc.gnu.org/g:93d5e1be87cab45513ac5ee524c773a6368f61d7

commit r17-3197-g93d5e1be87cab45513ac5ee524c773a6368f61d7
Author: Rohith Kapelli <[email protected]>
Date:   Sat Aug 8 00:03:56 2026 +0530

    aarch64: Avoid extra move for two-element vector lane copies [PR123951]

    Since r14-3381 the vec_extract/vec_set idiom used by the vcopy*_lane*
    intrinsics is folded to a VEC_PERM_EXPR, so the constant permute
    expander decides what to emit for it.  For a two-element vector the
    result takes one lane from each input, but the patterns that matched it
    tied the result to one particular input, and for half the lane
    combinations that is the wrong one, so the register allocator has to add
    a move.  On big endian arm_neon.h's lane flip puts
    vcopyq_laneq_u64 (a, 1, b, 1) in that half, so it regressed from one
    instruction to two and vect_copy_lane_1.c and vget_set_lane_1.c fail;
    little endian has the same problem on lane 0.

    Add two patterns for the two-element modes, each offering a second
    alternative that ties the destination to the other input, so that the
    register allocator can insert into whichever input already occupies the
    destination.  The first handles a lane copy whose source and destination
    lanes are the same; the second handles a lane insert from a scalar,
    which always sits in the low part of its register, so it is restricted
    to the case where the destination is architectural lane 0.  Both sit
    before the corresponding general patterns, which continue to handle
    every other case, including cross-lane copies.

    Both lane combinations of vcopy_lane_{s,u,f}32 and
    vcopyq_laneq_{s,u,f}64 now expand to a single INS on both endiannesses.
    The double add/sub merge in addsub_{1,2}.c uses the same two-element
    merge; with the tie left to the allocator its e1 case now inserts into
    lane 0 rather than lane 1, still a single INS, so the expected output is
    updated.

            PR tree-optimization/123951

    gcc/ChangeLog:

            * config/aarch64/aarch64-simd.md
            (*aarch64_simd_vec_set_lane0<mode>): New pattern.
            (*aarch64_simd_vec_copy_lane_same<mode>): New pattern.

    gcc/testsuite/ChangeLog:

            * gcc.target/aarch64/pr123951_1.c: New test.
            * gcc.target/aarch64/pr123951_2.c: New test.
            * gcc.target/aarch64/simd/addsub_1.c: Update e1 lane insert from
            d[1] to d[0].
            * gcc.target/aarch64/simd/addsub_2.c: Likewise.

    Signed-off-by: Rohith Kapelli <[email protected]>

Reply via email to