[X86] getHostCPUName() returns bdver1 under Windows-on-ARM x64 emulation; implied +fma4 makes JITs emit FMA4 the emulator faults on
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Summary
Under the Windows-on-ARM x64 emulator, the emulated CPUID identifies as **AuthenticAMD family 15h (Bulldozer) with AVX=1 but with the FMA4 and XOP bits clear**. `llvm::sys::getHostCPUName()` maps "AuthenticAMD family 15h" to `bdver1`/`bdver2`, and the `bdver*` processor models in `X86.td` **imply `+fma4`/`+xop` unconditionally**. Any JIT client that creates a TargetMachine with `MCPU = getHostCPUName()` (without explicitly subtracting `-fma4`) therefore emits 4-operand FMA4 instructions (`vfmaddps`), which the emulator cannot execute → `STATUS_ILLEGAL_INSTRUCTION` (0xc000001d).
No physical CPU with family 15h + AVX but without FMA4 ever shipped, so the name-implied feature set was historically safe — but emulators report exactly this combination: the feature bits are honest (FMA4=0), while the name-based table overrides them.
## Environment
- Windows 11 ARM64 build 26200 (25H2) guest (VMware Fusion / Apple M3 Max, but the CPUID profile comes from Windows' x64 emulator, not the hypervisor)
- x64 process running under the built-in x64-on-ARM64 emulation
- Observed with two independent LLVM-based GL JITs: Mesa 26.1.6 llvmpipe (mesa-dist-win, its bundled LLVM) and VMware's guest GL driver `vm3dgl64.dll` (embedded LLVM, older)
## CPUID as seen by the emulated x64 process
```
vendor: AuthenticAMD max_basic=0000000d max_ext=80000008
leaf 00000001: eax=00600f01 ebx=06080800 ecx=7ed83203 edx=17888911 ; family 15h
leaf 80000001: eax=00600f01 ebx=00000000 ecx=00000121 edx=28100800
FMA4 (80000001.ECX bit16) = 0
XOP (80000001.ECX bit11) = 0
AVX (1.ECX bit28) = 1, FMA3 (1.ECX bit12) = 1
```
## Crash evidence (minidump, faulting thread)
RIP in dynamically generated (JIT) memory:
```
0x...0469: c4 c3 f5 68 c8 20 vfmaddps ymm1, ymm1, ymm2, ymm8 ; FMA4, AMD-only
0x...046f: c4 e2 7d 18 57 04 vbroadcastss ymm2, dword ptr [rdi + 4]
0x...0475: c4 62 7d 18 47 10 vbroadcastss ymm8, dword ptr [rdi + 0x10]
0x...047b: c4 c3 b5 68 d0 20 vfmaddps ymm2, ymm9, ymm2, ymm8
```
Exception code 0xc000001d (STATUS_ILLEGAL_INSTRUCTION). Reproduces 100% (e.g. run any OpenGL app on Windows-on-ARM with mesa-dist-win llvmpipe as the app-local `opengl32.dll`; the first JITted vertex-path shader crashes the process).
## Why clients get bitten
`getHostCPUFeatures()` returns the honest bits (no fma4), but clients commonly pass `MCPU = getHostCPUName()` plus a *partial* feature delta. Mesa's gallivm, for example, builds its MAttrs list from its own CPU detection, which (since FMA4 support was dropped from Mesa) has no notion of fma4 — so nothing ever subtracts the name-implied `+fma4`. Correction to an earlier version of this report: I first wrote that Mesa's `LP_FORCE_SSE2=1` knob did not help — that test was void, the knob is compiled out in release builds (`#if MESA_DEBUG`). Mesa's `GALLIUM_OVERRIDE_CPU_CAPS=sse4.1`, which does reach release builds, DOES avoid the crash: it makes gallivm push `-avx` into MAttrs, and LLVM transitively clears FMA4 with it. So the name-implied `+fma4` is removable through an explicit negative MAttr — clients simply have no reason to pass one, since the CPUID bit they see is already 0.
## Suggested fix
Same class of problem as #130509, fixed for AArch64 in #160410 ("trust actual capabilities over CPU-name implications"). For X86 host detection, when `0x80000001.ECX` lacks the FMA4/XOP bits, `getHostCPUName()` should not return a `bdver*` name whose feature model implies them (return a name/tuning without those features, or verify the defining feature bits of the chosen model). Alternatively the name-implied features could be reconciled against `getHostCPUFeatures()` for the JIT ExecutionEngine default path.
## Workaround
JIT clients can pass explicit `-fma4,-xop` in MAttrs; end users can avoid affected JITs (for Mesa: `GALLIUM_DRIVER=softpipe`).
Contributor guide
Research direction
Start by tracing llvm::sys::getHostCPUName() and getHostCPUFeatures() through X86 host detection, then compare the selected name with the processor models and implied features in X86.td. The fix is done when a family-15h host reporting no FMA4 or XOP no longer causes the selected CPU name to imply those features, while valid feature reporting remains intact.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100