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

            Bug ID: 127712
           Summary: [AArch64][SVE] GCC fails to vectorize reverse
                    conditional gather/store loop due to possible alias
           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: ---

## [AArch64][SVE] GCC fails to vectorize reverse conditional gather/store loop
due to possible alias

GCC fails to vectorize the following reverse conditional loop on AArch64 SVE
due to a possible alias involving gather/scatter, although the input and output
pointers are declared `__restrict__`. Changing the loop direction to forward or
removing the conditional allows GCC to vectorize the loop. Clang considers the
original loop legal for vectorization and generates SVE code when vectorization
is explicitly enabled.

### Test case

```c
void foo(const int *__restrict__ data,
         int *__restrict__ out,
         int n)
{
    for (int i = n - 1; i >= 0; --i)
        if (i % 5 == 0)
            out[i] = data[i * 2];
}
```

### 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>:19:27: missed: couldn't vectorize loop
<source>:24:26: missed: possible alias involving gather/scatter between *_5 and
*_8
<source>:13:5: note: vectorized 0 loops in function.
<source>:33:17: note: ***** Analysis failed with vector mode VNx4SI
<source>:33:17: note: ***** Skipping vector mode VNx16QI, which would repeat
the analysis for VNx4SI
```

GCC therefore rejects the loop during vectorization analysis because of a
possible alias involving the gather/scatter accesses.

### Clang result

With Clang 22.1.0 and the following options:

```text
-S -O3 -ftree-vectorize -ftree-slp-vectorize --target=aarch64-linux-gnu
-march=armv9-a+sve -Rpass='.*vectorize.*' -Rpass-missed='.*vectorize.*'
-Rpass-analysis='.*vectorize.*'
```

adding

```c
#pragma clang loop vectorize(enable)
```

before the loop causes Clang to vectorize it successfully.

The generated SVE code computes a predicate for the conditional and uses
predicated indexed loads and stores. For example:

```asm
mul     z5.s, z5.s, z4.s
cmphs   p1.s, p0/z, z1.s, z5.s
...
ld1w    { z5.d }, p2/z, [x12, z5.d]
...
ld1w    { z7.d }, p2/z, [x12, z7.d]
...
st1w    { z5.s }, p1, [x11, x14, lsl #2]
```

This suggests that Clang considers the original loop feasible for vectorization
and that the required predicated gather/store operations are supported by the
target.

### Additional observation

The failure depends on both the loop direction and the conditional. Changing
the reverse loop to forward iteration allows GCC to vectorize it. Removing the
`if (i % 5 == 0)` condition from the reverse loop also allows GCC to vectorize
it.

This suggests that the failure may involve an interaction between reverse-loop
handling, conditional execution, and memory analysis for gather/scatter
accesses.

This case may be related to if-conversion during feasibility analysis.

### Actual behavior

GCC fails to vectorize the original reverse conditional loop and reports:

```text
missed: couldn't vectorize loop
missed: possible alias involving gather/scatter between *_5 and *_8
```

despite the input and output pointers being declared `__restrict__`.

In contrast, changing the loop direction to forward or removing the conditional
allows GCC to vectorize the loop, while Clang can vectorize the original
version when vectorization is explicitly enabled.

Reply via email to