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

            Bug ID: 127709
           Summary: [AArch64][SVE] GCC fails to vectorize reverse loop due
                    to possible alias involving gather/scatter
           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 reverse loop on AArch64 SVE due to a
possible alias involving gather/scatter, although the pointers are declared
`__restrict__`. Clang considers the same loop legal for vectorization and
generates SVE code when vectorization is explicitly enabled.

### Test case

```c
void foo(const int *__restrict__ a,
         const int *__restrict__ b,
         int *__restrict__ out,
         int n)
{
    for (int i = n - 1; i >= 0; --i)
        if (a[i] != 0)
            out[i] = a[i] + b[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
```

The same result is observed with `-fvect-cost-model=unlimited` and
`-ffast-math`.

### GCC output

```text
<source>:6:27: missed: couldn't vectorize loop
<source>:8:36: missed: possible alias involving gather/scatter between *_8 and
*_10
<source>:1:6: note: vectorized 0 loops in function.
<source>:8:27: note: ***** Analysis failed with vector mode 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.*'
```

Clang does not vectorize the loop by default because of its profitability
decision:

```text
<source>:7:5: remark: the cost-model indicates that vectorization is not
beneficial [-Rpass-missed=loop-vectorize]
<source>:7:5: remark: the cost-model indicates that interleaving is not
beneficial [-Rpass-missed=loop-vectorize]
```

However, adding

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

before the loop causes Clang to vectorize it successfully. The generated SVE
code contains predicated gather loads and a predicated store, for example:

```asm
cmpne   p1.s, p0/z, z3.s, #0
...
ld1w    { z4.d }, p2/z, [x13, z4.d]
...
ld1w    { z5.d }, p2/z, [x13, z5.d]
...
st1w    { z3.s }, p1, [x12, x15, lsl #2]
```

This suggests that Clang considers the loop legal and that the required
operations are supported by the target; its default rejection is due to
profitability rather than legality.

### Additional observation

The failure is sensitive to the loop direction. GCC reports `possible alias
involving gather/scatter` for the reverse loop, while changing only the
iteration direction to forward allows the loop to be vectorized.

The exact stride that triggers this diagnostic also depends on the element
types. This may suggest an interaction between reverse-loop handling and memory
analysis for gather/scatter accesses.

This case may be related to Memory during feasibility analysis.

### Actual behavior

GCC fails to vectorize the reverse loop and reports:

```text
missed: possible alias involving gather/scatter between *_8 and *_10
```

despite the input and output pointers being declared `__restrict__`.
Live examples reproducing the behavior are available on Compiler Explorer:
GCC: https://godbolt.org/z/cjze3v1Ta
Clang: https://godbolt.org/z/9T6Y641dG

Reply via email to