Skip to content

Commit b7a6ee4

Browse files
committed
v2 arm: gate simd_avx2's own test modules off v2; document the realizations
A per-test sweep of all 2541 lib tests under qemu -cpu Nehalem found 28 SIGILLs, all in simd_avx2's tests, u8x32_tests and f16_precision_tests, which call AVX2 intrinsics directly. No library path faulted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BMJnDBAfzcuQh5HeT39Rh
1 parent 2967d91 commit b7a6ee4

3 files changed

Lines changed: 45 additions & 8 deletions

File tree

‎.claude/plans/simd-sse-v2-tier-v1.md‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,27 @@ goes through `crate::simd`, so the switch is confined to `simd.rs`.
3030

3131
## Work items
3232

33-
- [ ] P0 TESTS FIRST: `v2-qemu` parity arm (`--config .cargo/config-v2.toml`,
33+
- [x] P0 TESTS FIRST: `v2-qemu` parity arm (`--config .cargo/config-v2.toml`,
3434
run under `qemu-x86_64-static -cpu Nehalem`) in `scripts/masking-parity.sh`
3535
and a `realization/v2` row in `simd-matrix.yaml`, with an objdump witness
3636
(no AVX instruction at all: no `%ymm`, no VEX `v`-prefixed op). Expect it
3737
to fail before the arm exists.
38-
- [ ] P1 `.cargo/config-v2.toml`; `simd.rs` routing; `cpu_guard` floor gated off
38+
- [x] P1 `.cargo/config-v2.toml`; `simd.rs` routing; `cpu_guard` floor gated off
3939
the v2 arm.
40-
- [ ] P2 close the API gap: compile v2, list every missing item, add each to
40+
- [x] P2 close the API gap: compile v2, list every missing item, add each to
4141
`simd_scalar.rs` (types `U8x32`, `F32Mask16`, `F64Mask8` and the x86-only
4242
methods). Safe Rust only.
43-
- [ ] P3 gates: lib tests on v2 under qemu Nehalem; parity on every arm; clippy
43+
- [x] P3 gates: lib tests on v2 under qemu Nehalem; parity on every arm; clippy
4444
v2/v3/v4/avx/baseline; codegen witness avx2/avx512 unchanged.
45-
- [ ] P4 docs: CLAUDE.md realization list, blackboard, `simd.rs` dispatch comment.
45+
- [x] P4 docs: CLAUDE.md realization list, blackboard, `simd.rs` dispatch comment.
46+
47+
## Outcome (2026-10-10)
48+
49+
- Per-test sweep: all 2541 v2 lib tests, each run as its own process under
50+
`qemu-x86_64-static -cpu Nehalem`. 28 faulted with SIGILL, every one in
51+
`simd_avx2`'s own test modules (`tests`, `u8x32_tests`,
52+
`f16_precision_tests`), which call AVX2 intrinsics directly. No library
53+
path faulted. Those three modules are now gated off the v2 arm.
54+
- Open: `crate::simd_avx2` stays public on v2 builds and has no startup
55+
check there, so a direct caller faults with SIGILL. Documented in the
56+
`simd.rs` module doc; the safe path is the `crate::simd` re-exports.

‎src/simd.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@
44
//! AVX-512 → AVX2 → Scalar. Consumer writes `crate::simd::F32x16`. Period.
55
//!
66
//! When `std::simd` stabilizes: swap this file. Zero consumer changes.
7+
//!
8+
//! The `Tier` above is runtime detection. The SIMD *types* are chosen at
9+
//! compile time, one realization per build, from the target features:
10+
//!
11+
//! * x86_64 `avx512f`: `simd_avx512.rs`.
12+
//! * x86_64 `avx2`, no `avx512f`: `simd_avx2.rs`. This arm is also what a
13+
//! baseline x86-64 build compiles, and `cpu_guard` refuses to start such a
14+
//! build on a CPU without AVX2.
15+
//! * x86_64 `avx`, no `avx2`: `simd_avx.rs` (`.cargo/config-avx.toml`).
16+
//! * x86_64 `sse4.2`, no `avx` (x86-64-v2, `.cargo/config-v2.toml`):
17+
//! `simd_scalar.rs`. The AVX2/AVX-512 types wrap 256/512-bit registers, so
18+
//! this arm uses plain arrays that LLVM compiles to SSE.
19+
//! * aarch64: NEON; wasm32 with `simd128`: `simd_wasm.rs`; any other target:
20+
//! `simd_scalar.rs`. The `nightly-simd` feature replaces all of these with
21+
//! `core::simd` for validation only.
22+
//!
23+
//! The module `crate::simd_avx2` stays public on every x86_64 build,
24+
//! including v2. Calling it directly on a CPU without AVX2 faults with
25+
//! SIGILL, and on the v2 arm no startup check catches it. Use the types
26+
//! re-exported from `crate::simd`.
727
828
#[cfg(feature = "std")]
929
use std::sync::LazyLock;

‎src/simd_avx2.rs‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,7 +3248,9 @@ impl Default for U8x32 {
32483248
// U8x32 tests
32493249
// ═══════════════════════════════════════════════════════════════════
32503250

3251-
#[cfg(all(test, target_arch = "x86_64"))]
3251+
// Off the x86-64-v2 arm: these call AVX2 intrinsics directly, and a v2 build
3252+
// (SSE4.2, no AVX) routes `crate::simd` to the scalar realization instead.
3253+
#[cfg(all(test, target_arch = "x86_64", not(all(target_feature = "sse4.2", not(target_feature = "avx")))))]
32523254
mod u8x32_tests {
32533255
use super::U8x32;
32543256

@@ -3446,7 +3448,9 @@ pub type i32x8 = I32x8;
34463448
#[allow(non_camel_case_types)]
34473449
pub type i64x4 = I64x4;
34483450

3449-
#[cfg(test)]
3451+
// Off the x86-64-v2 arm: these call AVX2 intrinsics directly, and a v2 build
3452+
// (SSE4.2, no AVX) routes `crate::simd` to the scalar realization instead.
3453+
#[cfg(all(test, not(all(target_feature = "sse4.2", not(target_feature = "avx")))))]
34503454
mod tests {
34513455
use super::*;
34523456

@@ -4001,7 +4005,9 @@ impl F16Scaler {
40014005
}
40024006
}
40034007

4004-
#[cfg(test)]
4008+
// Off the x86-64-v2 arm: these call AVX2 intrinsics directly, and a v2 build
4009+
// (SSE4.2, no AVX) routes `crate::simd` to the scalar realization instead.
4010+
#[cfg(all(test, not(all(target_feature = "sse4.2", not(target_feature = "avx")))))]
40054011
mod f16_precision_tests {
40064012
use super::*;
40074013

0 commit comments

Comments
 (0)