https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127459

            Bug ID: 127459
           Summary: [14/15/16 Regression] x86: AVX512VL instruction
                    (vinserti32x4, EVEX.256) emitted with only -mavx512f
           Product: gcc
           Version: 16.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: markrose at markrose dot ca
  Target Milestone: ---

Created attachment 65621
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65621&action=edit
Bug reproducer

## Description

With only AVX512F enabled, GCC emits `vinserti32x4` in its EVEX.256 (ymm) form,
which requires AVX512VL. `__AVX512VL__` is not defined at the time it does
this, and adding an explicit `-mno-avx512vl` does not suppress it.

The result is a binary that faults on a CPU implementing AVX512F but not
AVX512VL — Knights Landing / Knights Mill being the case that matters in
practice.

### Reproducer (attached as bug.c)

```c
void sink(int *);

void f(const unsigned *tab, unsigned long long k)
{
        int out[8];
        out[0] = tab[(k >>  0) & 15];
        out[1] = tab[(k >>  4) & 15];
        out[2] = tab[(k >>  8) & 15];
        out[3] = tab[(k >> 12) & 15];
        out[4] = tab[(k >> 16) & 15];
        out[5] = tab[(k >> 20) & 15];
        out[6] = tab[(k >> 24) & 15];
        out[7] = tab[(k >> 28) & 15];
        sink(out);
}
```

```
$ gcc -O3 -mavx512f -S bug.c -o -
...
        vinserti32x4    $0x1, %xmm1, %ymm0, %ymm0
...
```

The eight SLP-vectorised stores are combined into a 256-bit vector, and the
256-bit EVEX insert used to build it needs AVX512VL. Fewer than eight stores
does not trigger it.

### Expected

With AVX512F only, GCC should build the 256-bit value without an EVEX.256
encoding — the AVX (VEX) `vinserti128` form is available and is what GCC 13 and
earlier emit — or it should not vectorise this at 256 bits at all.

### Confirmation that the instruction really is unavailable

Running the same program under Intel SDE, once as a KNL and once as a
Skylake-X:

```
$ sde64 -knl -- ./bugtest
TID 0 SDE-ERROR: Executed instruction not valid for specified chip (KNL):
  0x...: vinserti32x4 ymm0, ymm0, xmm1, 0x1
Function: f

$ sde64 -skx -- ./bugtest
225 196 169 144 121 100 81 64
```

### Versions

| compiler | emits the VL instruction? |
| --- | --- |
| gcc 11.4.0 | no |
| gcc 12.4.0 | no |
| gcc 13.3.0 | no |
| **gcc 14.2.0 / 14.4.0** | **yes** |
| **gcc 15.3.0** | **yes** |
| **gcc 16.2.1 20260810** | **yes** |
| clang 14 / 18 / 19 / 22 | no |

So it is a regression introduced in GCC 14 and still present on current GCC.

### Flag variations (gcc 14.4, where -march=knl still exists)

| flags | emits it? |
| --- | --- |
| `-mavx512f` | yes |
| `-mavx512f -mno-avx512vl` | yes |
| `-march=knl` | yes |
| `-march=knl -mno-avx512vl` | yes |

`__AVX512VL__` is undefined in all four cases. `-march=knl` is the interesting
one: it names a CPU that has no AVX512VL at all, and GCC still generates the
instruction.

### Real-world impact

Found while building Mlucas (a GIMPS Lucas-Lehmer/PRP client) for Knights
Landing. Its `avx512_knl` build mode compiles with `-march=knl -mavx512f
-mavx512cd -mfma -mavx512er -mavx512pf`; on GCC 14 the resulting binary dies
immediately under SDE on the first such instruction in an FFT kernel. GCC 13
produces a working binary from the identical sources.

Across a representative set of Mlucas translation units the counts are: 0 for
GCC 11-13, 149 for GCC 14.4 with `-march=knl`, 202 for GCC 15.3 and 186 for GCC
16.2 (the latter two without `-march=knl`, which they no longer accept).

Mlucas is actively being used on many Knights Landing systems.

See: https://github.com/primesearch/Mlucas/pull/239

Reply via email to