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

Reply via email to