https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127928
Bug ID: 127928
Summary: [x86-64] Failure to vectorize a stride-2 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: ---
## Description
GCC 16.1.0 fails to vectorize a stride-2 loop containing a conditional store on
x86-64, reporting `no stmts to vectorize`.
Clang 22.1.0 successfully vectorizes the same loop with a vectorization width
of 8 and an interleaved count of 4, without requiring an explicit vectorization
pragma.
GCC can vectorize the loop when either the conditional store is removed or the
loop stride is changed from 2 to 1. The failure therefore appears to be
associated with the combination of a non-unit stride and a conditional store.
## Test case
```c
void foo(const int *__restrict__ a,
int *__restrict__ out,
int n)
{
for (int i = 0; i < n; i += 2) {
if (a[i])
out[i] = a[i];
}
}
```
## 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 -fvect-cost-model=unlimited
```
## GCC output
```text
<source>:6:23: missed: couldn't vectorize loop
<source>:6:23: missed: no stmts to vectorize.
<source>:2:6: note: vectorized 0 loops in function.
```
GCC generates a scalar loop with a conditional branch and scalar store:
```asm
.L4:
mov edx, DWORD PTR [rdi+rax*4]
test edx, edx
je .L3
mov DWORD PTR [rsi+rax*4], edx
.L3:
add rax, 2
cmp ecx, eax
jg .L4
```
## Comparison with Clang
### Clang version
```text
clang version 22.1.0
LLVM commit:
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 reports:
```text
<source>:6:5: remark: vectorized loop (vectorization width: 8, interleaved
count: 4) [-Rpass=loop-vectorize]
```
The generated assembly uses AVX2 instructions, including `vshufps`, `vpermpd`,
and `vpcmpeqd`, to process multiple iterations using SIMD operations.
Conditional stores are still performed individually using scalar stores.
## Additional observations
Two modifications allow GCC to vectorize the loop.
**1. Removing the conditional store while retaining stride 2:**
```c
void foo(int *__restrict__ out, int n)
{
for (int i = 0; i < n; i += 2)
out[i] = 1;
}
```
GCC successfully vectorizes this loop.
**2. Changing the stride from 2 to 1 while retaining the conditional store:**
```c
void foo(const int *__restrict__ a,
int *__restrict__ out,
int n)
{
for (int i = 0; i < n; ++i) {
if (a[i])
out[i] = a[i];
}
}
```
GCC also successfully vectorizes this loop.
These observations suggest that GCC's failure is related to handling
conditional stores in non-unit-stride loops, rather than either feature
individually.
## Live examples
GCC:
https://godbolt.org/z/xd184fde7
Clang:
https://godbolt.org/z/qWTbq71zc