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

Reply via email to