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