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