https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127924
Bug ID: 127924
Summary: Fully masked loop calls inbranch simdlen(32) SIMD
clone on inactive lanes (SIGFPE)
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: kyuwoncho18 at gmail dot com
Target Milestone: ---
Target: x86_64-pc-linux-gnu
Component: tree-optimization
godbolt: https://godbolt.org/z/j515dha5v (needs an AVX-512 executor; on a host
without it the binary dies with SIGILL instead)
```c
#include <stdio.h>
#pragma omp declare simd simdlen(32) inbranch
int __attribute__((noinline)) baz (int x) { return 1000 / x; }
short d[1024];
int b[1024];
void __attribute__((noipa))
foo (int n)
{
for (int i = 0; i < n; ++i)
{
d[i] = (short) (d[i] + 1);
if ((i & 1) == 0)
b[i] = baz (b[i]);
}
}
int main (void)
{
for (int i = 0; i < 1024; i++) { b[i] = i + 1; d[i] = 0; }
foo (17);
long s = 0;
for (int i = 0; i < 64; i++) s += b[i] + d[i];
printf ("%ld\n", s);
return 0;
}
```
GCC trunk miscompiles `foo` at -O2 on x86_64 with a fully masked loop:
```console
$ gcc -O2 -march=x86-64-v4 -mprefer-vector-width=512 -fopenmp-simd --param
vect-partial-vector-usage=2 t.c && ./a.out
Floating point exception (core dumped)
$ gcc -O2 -march=x86-64-v4 -mprefer-vector-width=512 -fopenmp-simd t.c &&
./a.out
4092
```
Expected `4092`: the scalar loop only calls `baz` for even `i < 17`, where
`b[i]` is 1..17, so no division by zero can happen. `-O0` and clang print
`4092`.
`vectorizable_simd_clone_call` passes the clone-call index `j` instead of the
sub-vector index `m` to `vect_get_loop_mask` at both `SIMD_CLONE_ARG_TYPE_MASK`
sites, inside `for (m = j * o; m < (j + 1) * o; m++)`. Here one simdlen(32)
call takes `o = 2` 16-lane mask parts (one per V16SI argument half), so the
second part (lanes 16-31) is ANDed with the loop mask of lanes 0-15 (all true),
while the matching `.MASK_LOAD` of `b` correctly uses the lanes 16-31 mask and
zero-fills lanes 17-31; the clone then runs `1000 / 0` on even lanes 18-30. The
mask synthesized further down for an unmasked call of an inbranch clone uses
`ncopies * o, mask_vectype, m`, which is correct.
Also fails with GCC 16.1 and 16.2; GCC 15.3 and older do not use the clone for
this loop. Not bisected; the `j` at the AVX-512 (integer mask_mode) site dates
from r16-5490 (PR122778), which added loop masking there.
Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.