https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127912
Bug ID: 127912
Summary: [x86-64] GCC fails to vectorize a reverse loop with a
conditional store
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 16.1.0 fails to vectorize a reverse loop containing a conditional store,
reporting `no vectype for stmt`.
The corresponding forward loop is successfully vectorized by GCC. Clang 22.1.0
also vectorizes the reverse loop under the same target architecture without
requiring an explicit vectorization pragma.
### Test case
```c
void foo(const float *__restrict__ a,
int *__restrict__ out,
int n)
{
for (int i = n - 1; i >= 0; --i) {
if (a[i] != 0.0f)
out[i] = 1;
}
}
```
### GCC version
```text
gcc version 16.1.0
```
### GCC options
```text
-S -O3 -ftree-vectorize -ftree-slp-vectorize
-march=x86-64-v3 -fopt-info-vec-all
```
### GCC output
```text
missed: couldn't vectorize loop
missed: not vectorized: no vectype for stmt: _4 = *_3;
scalar_type: const float
note: vectorized 0 loops in function.
```
### Comparison with GCC forward loop
Changing only the loop direction allows GCC to vectorize the loop:
```c
void foo(const float *__restrict__ a,
int *__restrict__ out,
int n)
{
for (int i = 0; i < n; ++i) {
if (a[i] != 0.0f)
out[i] = 1;
}
}
```
GCC reports:
```text
optimized: loop vectorized using 32 byte vectors and unroll factor 8
optimized: epilogue loop vectorized using 16 byte vectors and unroll factor 4
note: vectorized 1 loops in function.
```
### Comparison with Clang
Clang 22.1.0 successfully vectorizes the original reverse loop without a
vectorization pragma.
**Clang version:**
```text
clang version 22.1.0
(https://github.com/llvm/llvm-project.git
4434dabb69916856b824f68a64b029c67175e532)
```
**Clang options:**
```text
-S -O3 -ftree-vectorize -ftree-slp-vectorize
--target=x86_64-linux-gnu -march=x86-64-v3
-Rpass=.*vectorize.*
-Rpass-missed=.*vectorize.*
-Rpass-analysis=.*vectorize.*
```
**Clang output:**
```text
remark: vectorized loop (vectorization width: 8,
interleaved count: 4) [-Rpass=loop-vectorize]
```
The generated assembly contains SIMD instructions such as `vinsertps`,
`vinsertf128`, and `vcmpneqps`, demonstrating vectorization of the
floating-point comparisons across iterations, while the conditional stores
remain scalar.
### Additional observations
GCC successfully vectorizes a reverse loop with an unconditional store:
```c
void foo(const float *__restrict__ a,
int *__restrict__ out,
int n)
{
for (int i = n - 1; i >= 0; --i)
out[i] = a[i] != 0.0f;
}
```
GCC reports:
```text
optimized: loop vectorized using 32 byte vectors and unroll factor 8
optimized: epilogue loop vectorized using 16 byte vectors and unroll factor 4
```
These observations suggest that the missed vectorization is associated with the
combination of reverse iteration and conditional stores, rather than reverse
iteration or floating-point comparisons alone.
## Live examples
GCC:
https://godbolt.org/z/nfj47z7xv
Clang:
https://godbolt.org/z/vPGzaYMs3