fix(build): drop x86-64-v3 baseline so pre-Haswell CPUs don't SIGILL

Issue #353 reports v1.2.8 dying with "Illegal instruction (core
dumped)" at launch on Sandy Bridge (Intel HD 2000, 2011). The crash
is not in CMAF decrypt — it's the process never reaches user code.
Root cause: .cargo/config.toml set target-cpu=x86-64-v3 which is
the Haswell (2013) microarch level. LLVM then freely emits AVX2,
BMI2, FMA, LZCNT and MOVBE across the whole binary, including the
Rust/Tauri startup path. Any pre-Haswell x86_64 CPU (Sandy Bridge,
Ivy Bridge, AMD Bulldozer/Piledriver) SIGILLs on the first of those
instructions, long before CMAF decrypt or the UI mounts.

The x86-64-v3 baseline was added together with +aes,+ssse3 thinking
it was required to activate AES-NI. It is not. AES-NI is an
orthogonal ISA extension; target-feature=+aes alone is what gets
the aes crate to compile in the AES-NI code path, and its
cpufeatures::new! runtime CPUID check then dispatches to hardware
or software per-process. So the 40x CMAF decrypt speedup (22s ->
<500ms on a 208 MB HiRes bundle) came from +aes, not from v3.

Drop target-cpu=x86-64-v3. Keep target-feature=+aes,+ssse3:
  - Modern CPUs with AES-NI still get the hardware decrypt path.
  - CPUs without AES-NI get the software fallback via cpufeatures
    runtime dispatch — slower but correct, no crash.
  - SSSE3 has been in every x86_64 CPU since 2006 (Core 2).
  - Pre-Haswell CPUs stop SIGILLing at launch.

What we lose: some AVX2/BMI2 auto-vectorization in general codegen
(stdlib, symphonia decode paths). CMAF decrypt — the actual
bottleneck we were optimizing — is unaffected.

cc
This commit is contained in:
vicrodh committed 2026-04-23 08:43:42 -06:00
1 parent 20787766f7
commit b54574a786
1 file changed
+18 -9
+18 -9
View File
@@ -6,14 +6,23 @@
# clears 400+ MB/s. For HiRes (200 MB+ tracks) this is the difference
# between a 20-second gap and a sub-second one.
#
# Two things needed on x86_64:
# 1. `target-cpu=x86-64-v3` = Haswell microarchitecture baseline
# (2013+). Every CPU QBZ realistically runs on supports it. This
# gives AVX2, BMI2, etc. for general codegen.
# 2. `target-feature=+aes,+ssse3` to explicitly enable the AES-NI
# instruction set — which is NOT included in x86-64-v3 as a
# microarch level. Without this flag the `aes` crate's hardware
# dispatch never gets compiled in, no matter how capable the CPU.
# What we need is ONLY the AES-NI instruction set compiled in. The
# `aes` crate uses `cpufeatures::new!` to do a runtime CPUID check
# before dispatching to the hardware path, so as long as the AES-NI
# code is present in the binary, CPUs without AES-NI fall back to the
# software implementation gracefully — no crash, just slower decrypt.
#
# `target-feature=+aes,+ssse3` is what enables that compile-in.
# SSSE3 has been in every x86_64 CPU since 2006 (Core 2).
#
# We deliberately do NOT set `target-cpu=x86-64-v3` (Haswell baseline,
# 2013). v3 includes AVX2/BMI2/FMA/LZCNT/MOVBE and LLVM will freely
# emit those instructions anywhere in the binary — including the
# startup path, long before CMAF runs. On pre-Haswell CPUs (Sandy
# Bridge 2011, Ivy Bridge 2012, AMD Bulldozer/Piledriver) the process
# dies with SIGILL at launch. See issue #353. Raising the baseline
# gave no CMAF speedup — the perf win came entirely from `+aes` — so
# we keep the AES-NI path and drop the incompatible baseline.
#
# IMPORTANT: these flags MUST be scoped to x86_64 targets. Using
# `[build] rustflags = ...` applies them to every target, which on
@@ -23,4 +32,4 @@
# get their own AES/crypto extensions automatically via `aes` crate's
# armv8 path — we don't need to force anything there.
[target.'cfg(target_arch = "x86_64")']
rustflags = ["-C", "target-cpu=x86-64-v3", "-C", "target-feature=+aes,+ssse3"]
rustflags = ["-C", "target-feature=+aes,+ssse3"]