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

Reply via email to