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

            Bug ID: 128324
           Summary: [17 Regression] wrong code with vdup_lane_s16 on
                    big-endian ARM with -mfloat-abi=softfp
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yuki.tanaka at defaultcase dot de
  Target Milestone: ---

#include <arm_neon.h>
#include <stdint.h>

__attribute__((noipa)) int16x4_t a(int16x4_t v)
{
  return vdup_lane_s16(v, 3);
}

int main(void)
{
  int16_t in[4] = { 10, 11, 12, 13 };
  int16_t out[4];

  vst1_s16(out, a(vld1_s16(in)));

  if (out[0] != 13)
    __builtin_abort();

  return 0;
}

vdup_lane_s16(v, 3) copies lane 3 into all lanes, so out[0] must be 13. Instead
a returns lane 1 (11 in every lane) and main aborts. This happens with -O2
-mbig-endian -march=armv7-a -mfpu=neon -mfloat-abi=softfp, also at -O1;
little-endian is fine. vdupq_lane_s16, vdup_lane_s32 and vdup_lane_s8 pick the
wrong lane too.

Compiler Explorer:
https://godbolt.org/z/cP8x8cebY

GCC 17:
a:
        lsrs    r3, r1, #16
        vdup.16 d16, r3
        vmov    r1, r0, d16  @ v4hi
        bx      lr

GCC 16.1:
a:
        vmov    d16, r1, r0  @ v4hi
        vdup.16 d16, d16[3]
        vmov    r1, r0, d16  @ v4hi
        bx      lr

On big-endian, lane 3 is in the high half of r0, but GCC 17 extracts the high
half of r1 (lane 1).

Possibly related to commit r17-2930-g2354f269895("arm: handle neon vec_dup from
select of 128-bit vector").

Reply via email to