https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127713
Bug ID: 127713
Summary: [AArch64][SLP] GCC fails to vectorize four-field
reduction with loop step 3
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: bug_hunters at yeah dot net
Target Milestone: ---
GCC fails to vectorize the following loop on AArch64 and reports `unsupported
SLP instances`. Clang is able to SLP-vectorize the four-field horizontal
reduction in the same loop and generates NEON vector instructions.
Interestingly, changing only the loop step from 3 to 1 or 2 allows GCC to
vectorize the loop.
### Test case
```c
typedef struct {
char a, b, c, d;
} S;
void foo(const S *__restrict__ x,
long *__restrict__ out,
int n)
{
for (int i = 0; i < n; i += 3) {
out[i] = (long)x[i].a + x[i].b + x[i].c + x[i].d;
if (x[i].c > 100)
break;
}
}
```
### GCC version
```text
aarch64-unknown-linux-gnu-g++ (GCC) 16.1.0
```
### GCC options
```text
-O3 -march=armv9-a+sve -ftree-vectorize -fopt-info-vec-all
```
### GCC output
```text
<source>:9:23: missed: couldn't vectorize loop
<source>:9:23: missed: unsupported SLP instances
<source>:5:6: note: vectorized 0 loops in function.
<source>:10:49: note: ***** Analysis failed with vector mode VNx16QI
<source>:10:49: note: ***** The result for vector mode VNx16QI would be the
same
<source>:10:49: note: ***** Re-trying analysis with vector mode VNx8QI
<source>:10:49: note: ***** Analysis failed with vector mode VNx8QI
<source>:10:49: note: ***** Re-trying analysis with vector mode VNx4QI
<source>:10:49: note: ***** Analysis failed with vector mode VNx4QI
<source>:10:49: note: ***** Re-trying analysis with vector mode VNx2QI
<source>:10:49: note: ***** Analysis failed with vector mode VNx2QI
<source>:10:49: note: ***** Re-trying analysis with vector mode V16QI
<source>:10:49: note: ***** Analysis failed with vector mode V16QI
<source>:10:49: note: ***** Re-trying analysis with vector mode V8QI
<source>:10:49: note: ***** Analysis failed with vector mode V8QI
<source>:10:49: note: ***** Re-trying analysis with vector mode V4HI
<source>:10:49: note: ***** Analysis failed with vector mode V4HI
<source>:10:49: note: ***** Re-trying analysis with vector mode V2SI
<source>:10:49: note: ***** Analysis failed with vector mode V2SI
```
GCC therefore rejects the loop during vectorization analysis with `unsupported
SLP instances`.
### Clang result
Clang 22.1.0 is able to SLP-vectorize the four-field reduction in the step-3
version.
With:
```text
-S -O3 -ftree-vectorize -ftree-slp-vectorize --target=aarch64-linux-gnu
-march=armv9-a+sve -Rpass='.*vectorize.*' -Rpass-missed='.*vectorize.*'
-Rpass-analysis='.*vectorize.*'
```
Clang reports:
```text
<source>:10:31: remark: Vectorized horizontal reduction with cost -3 and with
tree size 2 [-Rpass=slp-vectorizer]
```
The generated code contains NEON instructions implementing the horizontal
reduction:
```asm
ldur s0, [x8, #-2]
ushll v0.8h, v0.8b, #0
addv h0, v0.4h
umov w10, v0.h[0]
str x10, [x1], #24
```
The early-exit condition is also preserved:
```asm
ldrb w11, [x8], #12
cmp w11, #100
...
b.hi .LBB0_4
```
Thus, Clang is able to SLP-vectorize the computation inside the loop while
preserving the early exit.
### Additional observation
The failure is sensitive to the loop step. Changing only
```c
i += 3
```
to
```c
i += 1
```
or
```c
i += 2
```
allows GCC to vectorize the loop.
For example, with step 1, GCC generates vector code including:
```asm
ld4 {v24.16b - v27.16b}, [x4]
uaddl v23.8h, v24.8b, v25.8b
uaddl v29.8h, v26.8b, v27.8b
add v29.8h, v29.8h, v23.8h
```
and also performs a vector comparison for the early-exit condition:
```asm
cmphi p15.b, p7/z, z31.b, #100
b.none .L13
```
Therefore, GCC is able to vectorize closely related versions of the loop and
handle the early-exit condition, but the step-3 version is rejected with
`unsupported SLP instances`.
This suggests that the failure may involve an interaction between the non-unit
loop step and SLP analysis. The exact root cause may require further
investigation.
This case may be related to Instruction Semantics during feasibility analysis.
### Actual behavior
GCC fails to vectorize the step-3 version and reports:
```text
missed: couldn't vectorize loop
missed: unsupported SLP instances
```
while Clang SLP-vectorizes the horizontal reduction and emits NEON `ushll` and
`addv` instructions.
Changing the loop step from 3 to 1 or 2 also allows GCC to vectorize the loop.
Live examples reproducing the behavior are available on Compiler Explorer:
GCC: https://godbolt.org/z/Tf96rKnd7
Clang: https://godbolt.org/z/Pn68vxc7z