llvm / llvm/llvm-project

[ARM][NEON] vuzp.16 not emitted for vuzpq_p16 on ARM big-endian

Open
#222,833 3 comments 0 reactions 0 assignees View on GitHub
backend:ARM NEON
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Summary
On the ARM big-endian NEON target, the `vuzp.16` instruction is no longer emitted for the `vuzpq_p16` NEON intrinsic. It degenerates into a long sequence of element-by-element `vmov` moves between NEON lanes and GPRs. The little-endian target lowers the same source to a single `vuzp.16`, so this is a big-endian-specific code-quality regression.

## Environment
- LLVM/clang version: clang(trunk)
- Target: ARM big-endian

## Reproducer
https://godbolt.org/z/M3TE6csoh

```c
// vuzpqp16.c
#include "arm_neon.h"

poly16x8x2_t test_vuzpqp16(poly16x8_t _a, poly16x8_t _b)
{
return vuzpq_p16(_a, _b);
}
```

Compile

```bash
clang vuzpqp16.c -O1 -mfpu=neon -mfloat-abi=softfp -S -o vuzp_le.s
clang vuzpqp16.c -O1 -mfpu=neon -mfloat-abi=softfp -mbig-endian -S -o vuzp_be.s
```

## Actual behavior
### Little-endian

```asm
test_vuzpqp16:
vmov d16, r2, r3
vldr d17, [sp]
add r1, sp, #8
vld1.64 {d18, d19}, [r1]
vuzp.16 q8, q9
vst1.16 {d16, d17}, [r0]!
vst1.64 {d18, d19}, [r0]
bx lr
```

### Big-endian

```asm
test_vuzpqp16:
vldr d19, [sp]
add r1, sp, #8
vmov d18, r3, r2
vld1.64 {d16, d17}, [r1]
vrev64.16 q10, q8
vmov.u16 r1, d21[0]
vmov.16 d17[0], r1
vmov.u16 r1, d21[2]
vmov.16 d17[1], r1
vmov.u16 r1, d20[0]
vmov.16 d17[2], r1
vmov.u16 r1, d20[2]
vmov.16 d17[3], r1
vmov.u16 r1, d21[1]
vmov.16 d23[0], r1
vmov.u16 r1, d21[3]
vmov.16 d23[1], r1
vmov.u16 r1, d20[1]
vmov.16 d23[2], r1
vmov.u16 r1, d20[3]
vmov.16 d23[3], r1
vrev64.16 q9, q9
vmov.u16 r1, d19[1]
vmov.16 d22[0], r1
vmov.u16 r1, d19[3]
vmov.16 d22[1], r1
vmov.u16 r1, d18[1]
vmov.16 d22[2], r1
vmov.u16 r1, d18[3]
vmov.16 d22[3], r1
vst1.16 {d22, d23}, [r0]!
vmov.u16 r1, d19[0]
vmov.16 d16[0], r1
vmov.u16 r1, d19[2]
vmov.16 d16[1], r1
vmov.u16 r1, d18[0]
vmov.16 d16[2], r1
vmov.u16 r1, d18[2]
vmov.16 d16[3], r1
vrev64.16 q8, q8
vst1.64 {d16, d17}, [r0]
bx lr
```

Contributor guide

Open the contributing guide

Research direction

Start with the vuzpq_p16 reproducer in vuzpqp16.c and compare the little-endian and big-endian assembly produced by the listed clang commands. Investigate the ARM NEON lowering path for this intrinsic and verify the fix by checking that the big-endian output emits vuzp.16 rather than the shown lane-by-lane vmov sequence.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.