build: enforce -march=x86-64-v2 on Linux x86_64

GCC 11+ on Intel CI runners (Skylake-X, Ice Lake, Sapphire Rapids)
emits AVX-512/AVX10 instructions for std::string / memcpy inlining
that crash with SIGILL on AMD EPYC and older Intel without those
extensions. Root cause: libstdc++ is statically linked into the
binary, so the build host's instruction set becomes a hard runtime
requirement.

The CI binary crashed immediately on DNS2/DNS3 (AMD EPYC Milan) with:
  traps: trianglesd[...] trap invalid opcode ip:...e432 error:0
  in trianglesd[...+af3000]
Disassembly of the crash site (file offset 0x15b432):
  62 f1 7f 08 6f 41 ff   vmovdqu8 -0x10(%rcx), %xmm0
This is an AVX10/AVX-512 instruction emitted inside
std::basic_string::basic_string (statically linked libstdc++).

Fix: -march=x86-64-v2 -mtune=generic for all Linux x86_64 builds.
v2 baseline (SSE4.2 + POPCNT + CMPXCHG16B) is from 2009 Nehalem and
supported on every x86_64 CPU we ship to. Override-able via
-DCMAKE_X86_64_BASELINE=OFF if a CPU-specific build is needed.
This commit is contained in:
2026-07-01 03:26:31 -07:00
parent b6feab8e94
commit 5635cb5e57
+24
View File
@@ -47,6 +47,30 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "i[3-6]86")
add_compile_options(-msse2)
endif()
# ── x86-64 baseline ISA (portability across CPU vendors/models) ──
# CRITICAL: Without this, GCC on Intel CI runners (Skylake-X, Ice Lake,
# Sapphire Rapids) emits AVX-512 / AVX10 instructions (vmovdqu8, vpcompressd,
# vpopcntd, etc.) for std::string / memcpy inlining that CRASH with SIGILL
# on AMD EPYC (Milan, Genoa) and older Intel without AVX-512/AVX10.
# x86-64-v2 = baseline from ~2009 (Nehalem): SSE4.2 + POPCNT + CMPXCHG16B.
# Supported on EVERY x86_64 CPU Triangles runs on in production (DNS2, DNS3,
# Hetzner ARM64 excluded — that's a different build). Do NOT raise to v3
# (AVX2) without re-testing on every supported CPU; v3 is fine for most
# modern hardware but adds risk on edge cases (early Ryzen, Atom).
# Override with -DCMAKE_X86_64_BASELINE=OFF to disable (not recommended).
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$" AND NOT WIN32 AND NOT APPLE)
option(CMAKE_X86_64_BASELINE
"Compile with -march=x86-64-v2 (SSE4.2 baseline) for portability across CPU vendors"
ON)
if(CMAKE_X86_64_BASELINE)
add_compile_options(-march=x86-64-v2)
# -mtune=generic tells GCC the binary will run on CPUs other than the
# build host. Combined with -march=x86-64-v2 above, the scheduler
# picks instructions from the v2 subset only — no AVX-512 leaks.
add_compile_options(-mtune=generic)
endif()
endif()
# ── Platform: Windows (MSYS2 MinGW64) ──
if(WIN32)
add_compile_options(-Wa,-mbig-obj)