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").