You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9402e57
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: .claude/blackboard.md
+28Lines changed: 28 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,23 @@
1
+
## 2026-10-10 — `simd_avx.rs`: AVX-without-AVX2 realization (Sandy/Ivy Bridge, Bulldozer–Jaguar), plus three pre-existing x86 fixes
2
+
3
+
-**What:** a seventh realization, selected at compile time by `all(target_feature = "avx", not(target_feature = "avx2"))`. You get it with `target-cpu=native` on such a CPU, or with `.cargo/config-avx.toml` (`sandybridge`). The types and the `simd.rs` exports are unchanged; the 49 AVX2-only items in `simd_avx2.rs` and 19 in `simd_avx512.rs` are cfg-gated, and `simd_avx.rs` supplies the same methods from SSE2–SSE4.1 halves plus AVX1 float-domain ops. There are no runtime feature checks. The `cpu_guard` AVX2 startup floor applies only when the AVX2 arm is compiled in. Baseline builds (no `avx` cfg) are UNCHANGED: they keep the AVX2 arm and the floor. Whether the SSE tier should take them over is an open operator question.
4
+
-**Evidence:**
5
+
-`scripts/masking-parity.sh avx-qemu` passes all 15 groups under `qemu-x86_64-static -cpu SandyBridge`, with header `avx2=false avx512f=false`.
6
+
- 422 `simd` lib tests pass on that arm under qemu.
7
+
- The CI `realization/avx` row runs both, plus an objdump witness. The witness checks the parity binary for AVX2 integer ymm ops, FMA3 and F16C, and finds none. It can fire: the AVX2-op check finds 20,162 hits on a v3 binary. Its FMA/F16C check has never been seen to fire, because the parity program never calls `mul_add`; the unit test under qemu covers that case instead.
8
+
- Clippy `-D warnings` is clean on v3, v4, avx and baseline. Lib tests pass on v3 (2510) and v4 (2561). Codegen witness avx2/avx512 and parity v3/v4 PASS.
9
+
-**sentinel-qa BLOCK, fixed:**`F32x8::mul_add` called `_mm256_fmadd_ps` ungated, and F32x8 is exported on this arm, so a Sandy Bridge build faulted. It now has `cfg(target_feature = "fma")` with a per-lane `f32::mul_add` fallback (fused, one rounding). Test `f32x8_mul_add_is_fused` separates fused from unfused rounding. Disable: forcing the FMA body on the AVX build gives SIGILL under qemu. The F16C sites in `simd_avx512.rs` are runtime-detected and need nothing.
10
+
-**Pre-existing bugs found and fixed:**
11
+
-`simd_avx2::dot_i8`, a safe `pub fn` with no in-tree callers: `vpmaddubsw` saturated at `a = b = 127` (4080 instead of 516128), and a shorter `b` was read past its end. This is inventory row 410. Both arms now use `pmovsxbw` + `pmaddwd`, fold into an i64 every 16,384 chunks, and sum over `min` length. Test `simd_avx2_dot_i8_is_exact` is red on the old code on both arms.
12
+
- Five x86 256-bit methods had **no test on any stable arm**: `U16x16::{mullo, blend_epi32}`, `U8x32::shuffle_bytes`, `I8x32::cmp_gt` and `I16x16::cmp_gt`. Found because their disable runs stayed green. Test `x86_256bit_integer_methods_match_scalar` now checks them against scalar references on every x86 arm.
13
+
-**Disable runs on `simd_avx.rs`, all red, each restored:** cmpgt bias dropped (6 tests), `reduce_min` shuffle, saturating sub → wrapping, `transpose8` unpack swap, blend operand swap, I8 cmp_gt operand swap, I16 cmp_gt half swap, shuffle operand swap, mullo → mulhi. The first run of the I16 half swap crashed qemu itself (`QEMU internal SIGSEGV`) under the multithreaded harness. That is not a detection; single-threaded, the assertion fails as it should.
14
+
-**Unsafe:** 29 new blocks in `simd_avx.rs`, all SAFETY-commented, verdict IRREDUCIBLE. They are appended to `.claude/knowledge/unsafe-inventory/sites.tsv` with a README addendum.
15
+
-**Open:**
16
+
- The SSE-tier scope decision (all non-AVX builds vs only v2 builds).
17
+
- The `saturating_abs` SSSE3 patch, awaiting approval.
18
+
-`dot_i8` changed its results; it has no in-tree callers, so the effect on external consumers is unknown.
## 2026-10-08 — `PillarReport::deferred` + `certified()`; `Cascade::query` documents that Stroke 1 can drop true hits
2
22
3
23
-**Pillars:** Pillar-15/16/17 run no probe but report `passed = true`. A gate on `passed` counted them as certified. `PillarReport` now has `deferred: bool` (true only for those three) and `certified() = passed && !deferred`. `print()` shows `DEFERRED`. `passed` keeps its meaning, so existing callers do not change.
src/simd_avx.rs 42 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe { (_mm256_castsi256_si128(v), _mm256_extractf128_si256::<1>(v)) }
1304
+
src/simd_avx.rs 49 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe { _mm256_set_m128i(hi, lo) }
1305
+
src/simd_avx.rs 59 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe { join($op(al, bl), $op(ah, bh)) }
1306
+
src/simd_avx.rs 69 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe { _mm256_castps_si256($op(_mm256_castsi256_ps($a), _mm256_castsi256_ps($b))) }
1307
+
src/simd_avx.rs 79 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe { (_mm_movemask_epi8(lo) as u32 & 0xFFFF) | ((_mm_movemask_epi8(hi) as u32) << 16)
1308
+
src/simd_avx.rs 93 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let mut sum = unsafe {
1309
+
src/simd_avx.rs 133 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let mut result = unsafe {
1310
+
src/simd_avx.rs 174 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1311
+
src/simd_avx.rs 192 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic,raw_load_store,ptr_arith unsafe {
1312
+
src/simd_avx.rs 212 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic,raw_load_store,ptr_arith unsafe { _mm256_loadu_pd(v.0.as_ptr().add(4 * half) as *const f64) }
1313
+
src/simd_avx.rs 219 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let c = unsafe {
1314
+
src/simd_avx.rs 235 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic,raw_load_store,ptr_arith unsafe { _mm256_storeu_pd(out[4 * bj + k].0.as_mut_ptr().add(4 * bi) as *mut f64, v) };
1315
+
src/simd_avx.rs 276 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic,raw_load_store,ptr_arith core::array::from_fn(|k| unsafe { _mm_loadu_si128(self.0.as_ptr().add(4 * k) as *const __m
1316
+
src/simd_avx.rs 284 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1317
+
src/simd_avx.rs 297 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1318
+
src/simd_avx.rs 314 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let q = unsafe { _mm_movemask_ps(_mm_castsi128_ps(_mm_cmpgt_epi32(a[k], b[k]))) as u32 };
1319
+
src/simd_avx.rs 332 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1320
+
src/simd_avx.rs 343 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1321
+
src/simd_avx.rs 360 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic Self(unsafe { _mm256_permute2f128_si256::<IMM>(self.0, other.0) })
1322
+
src/simd_avx.rs 370 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic Self(unsafe {
1323
+
src/simd_avx.rs 394 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1324
+
src/simd_avx.rs 478 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let ones = unsafe { _mm256_set1_epi16(-1) };
1325
+
src/simd_avx.rs 496 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic,raw_load_store,ptr_arith unsafe {
1326
+
src/simd_avx.rs 527 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic let bias = unsafe { _mm256_set1_epi8(i8::MIN) };
1327
+
src/simd_avx.rs 562 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1328
+
src/simd_avx.rs 573 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1329
+
src/simd_avx.rs 605 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic Self(unsafe { join(_mm_blendv_epi8(bl, al, ml), _mm_blendv_epi8(bh, ah, mh)) })
1330
+
src/simd_avx.rs 688 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
1331
+
src/simd_avx.rs 755 FORK block src IRREDUCIBLE present - SSE2-SSE4.1/AVX1 intrinsics on the AVX-without-AVX2 arm; still E0133 on rustc 1.99 (see probe table), so the block cannot be removed x86_intrinsic unsafe {
|`popcount`, `dot_i8` (free fns) |`simd_avx2.rs`| re-exported from `simd_avx` on the arm |
47
+
|`I8x32`, `I16x16`|`simd_avx512.rs`| 6 + 5 methods, 4 traits each |
48
+
|`F32x8::mul_add`|`simd_avx512.rs`| FMA3, not AVX2 — missed by the AVX2-only scan, caught by sentinel-qa; now `cfg(target_feature = "fma")` with a per-lane `f32::mul_add` fallback |
49
+
50
+
49 gates in `simd_avx2.rs`, 19 in `simd_avx512.rs`. F16C sites in
51
+
`simd_avx512.rs` are runtime-detected (`is_x86_feature_detected!`) and need none.
52
+
53
+
## Work items
54
+
55
+
-[x] P0 TESTS FIRST: a `native-avx` arm in `crates/simd-masking-parity`
56
+
(`--config .cargo/config-avx.toml`, run under `qemu-x86_64-static -cpu
57
+
SandyBridge`), wired into `scripts/masking-parity.sh` and the
58
+
`simd-matrix` CI workflow. Expect it to SIGILL before the backend exists.
59
+
-[x] P1 `.cargo/config-avx.toml`; arm predicate; `cpu_guard` floor gated.
60
+
-[x] P2 split the affected impl blocks (no behaviour change on other arms;
61
+
codegen-witness avx2/avx512 must stay byte-for-byte green).
62
+
-[x] P3 `simd_avx.rs` per type, one type per chunk (U8x32, U16x16, U64x8,
0 commit comments