09 — SIMD Architecture¶
1. Purpose¶
How per-ISA code is organized, compiled, and kept correct: target regions, translation-unit rules, tail handling, the shared compaction machinery, and per-ISA engineering notes. Upstream authority: Charter §6.3 (ISA matrix), §4-adoption case (per-ISA first-party, no abstraction layer), Survey §4 (SIMD design space).
2. Requirements¶
| ID | Requirement |
|---|---|
| REQ-SIMD-001 | ISA-specific intrinsics shall appear only in <family>_avx2.cpp, <family>_neon.cpp, <family>_avx512.cpp, and kernel_common.h-declared helpers compiled therein. No intrinsics in public headers, _scalar_impl.h, or scalar TUs (REQ-REPO-004). |
| REQ-SIMD-002 | x86 ISA code shall be enabled by target-region macros (QUIVER_TARGET_AVX2_BEGIN/END, QUIVER_TARGET_AVX512_BEGIN/END) expanding to #pragma GCC target / Clang attribute push blocks — never by global -m flags (REQ-BUILD-005). MSVC exception: per-TU /arch flags (03 §3). NEON needs no region on ARM64 (baseline). |
| REQ-SIMD-003 | Tail policy (ADR-015): AVX2/NEON backends process ⌊n/W⌋ full vectors then a scalar tail (< W elements) — no masked-overread tricks. AVX-512 backends may use masked loads/stores for tails: architecturally, masked-out lanes are not accessed and cannot fault (Intel SDM guarantee); this satisfies REQ-MEM-001's architectural observable-access clause and shall be validated by guard-page tests under SDE and by the sanitized SDE leg of REQ-CI-004 (Clang, whose ASan instruments llvm.masked.* lowering; the sanitized AVX-512 leg is Clang-only for this reason). |
| REQ-SIMD-004 | The AVX-512 required feature set is F+BW+DQ+VL (dispatch precondition, REQ-DISP-004); VBMI2/VPOPCNTDQ are optional sub-features selected at resolution time (REQ-DISP-011). AVX-512 code shall not use any extension outside {F, BW, DQ, VL, VBMI2, VPOPCNTDQ}. |
| REQ-SIMD-005 | Compaction LUTs are shared MOD-KCOMMON data: AVX2 32-bit: 256-entry × 8×uint32_t permutation table (8 KiB, alignas(64)); 64-bit: 16-entry × 4×uint64_t nibble table; 8/16-bit + NEON: 16-entry × 8-byte nibble pshufb/TBL tables; all generated by consteval functions and runtime-re-derived in tests (05 §6). Total LUT budget ≤ 16 KiB. |
| REQ-SIMD-006 | _scalar_impl.h files shall compile cleanly inside any target region (no ISA macros, no target-dependent behavior) — the mechanism enabling equal-ISA autovec baselines (ADR-011) and the amalgamation (ADR-018). CI lint greps these files for intrinsic headers and target macros. |
| REQ-SIMD-007 | Unaligned memory access in SIMD code shall use unaligned intrinsics (loadu/storeu, plain NEON vld1/vst1) or memcpy; aligned-only intrinsics (load/store) are prohibited (REQ-MEM-004; enforcement: clang-tidy custom check list + review). |
| REQ-SIMD-008 | Throughput-critical NEON loops shall sustain ≥ 4 independent 128-bit operations in flight (unroll ≥ 4) — Apple Firestorm's 4×128-bit pipes (Survey §3.1, §4.1). Verified as benchmark evidence, not a hard gate. |
| REQ-SIMD-009 | A nightly CI job shall compile scalar TUs with -Rpass-missed=loop-vectorize (Clang) and publish the report as an artifact — silent devectorization of the autovec baseline is a tracked regression signal (Survey §4.4), informational only. |
| REQ-SIMD-010 | SVE2 shall not appear in v1 sources. The exploratory branch (Charter §6.3) lives outside main and outside this PRD's scope (21-future-work.md). |
3. ADR-003 — Per-ISA translation units with target-region macros¶
- Status: Accepted.
- Context: shipped binaries must run on baseline CPUs while containing AVX2/AVX-512 code (Charter §6.3 conservative-baseline dispatch); the amalgamation must compile as one TU (ADR-018); MSVC lacks function-level target attributes (tier-2).
- Problem: how ISA code gets compiled without global flags and without UB (calling AVX2 code on a non-AVX2 CPU is prevented by dispatch; compiling it must not leak into baseline paths).
- Alternatives:
- Per-TU
-mavx2flags only — works for the normal build, fails amalgamation (single TU) and risks the compiler auto-vectorizing shared inline helpers with AVX2 into code reachable from baseline paths (a classic latent-crash bug class). - GCC/Clang function multiversioning (
target_clones) — rejected: uneven MSVC/AppleClang support, ifunc coupling (see ADR-004 alt 1), less explicit dispatch. - Highway/xsimd abstraction — charter-prohibited (Charter §4 decision).
- Target-region macros around whole implementation namespaces in dedicated TUs (selected): the TU boundary provides organizational isolation; the pragma region provides flag-independent compilation; identical source works in normal and amalgamated builds.
- Decision: Alternative 4; regions defined once in
target_regions.h; every symbol inside a region lives inquiver::detail::<isa>namespaces so cross-region leakage is nameable and lintable. - Consequences: + one mechanism everywhere; − pragma dialect differences GCC vs Clang (encapsulated in the two macros), MSVC needs the per-TU-flag fallback and amalgamation narrowing (ADR-018).
- Reconsideration: if a tier-1 compiler regresses target-pragma codegen quality (tracked by ledger deltas per compiler).
- Related: REQ-SIMD-001/002/006, REQ-BUILD-005, ADR-018.
4. ADR-015 — Tail handling policy¶
- Status: Accepted.
- Context: Charter §7.2 no-over-read default; batch tails (
n mod W) are the classic over-read temptation. - Alternatives: (1) read-past-end with page-boundary checks — rejected outright: violates the charter's sanitizer-clean pledge, unvendorable; (2) require padded buffers — rejected: that is the
_paddedvariant family, deliberately not shipped in v1 (REQ-MEM-002); (3) scalar tails everywhere — safe but leaves AVX-512 masking value unused; (4) scalar tails on AVX2/NEON + native masking on AVX-512 (selected) — masking is architecturally access-suppressing, keeping the contract while showcasing the ISA (Survey §4.1: "the ISA matters more than the width"). - Consequences: tail code is a per-family shared helper (MOD-KCOMMON); guard-page tests place batch ends flush against protected pages for every kernel × ISA (12 §2, REQ-TEST-006).
- Reconsideration: ledger evidence that scalar tails dominate small-batch cost for a hot family may motivate
_paddedvariants — via the REQ-MEM-002 amendment path, never silently. - Related: REQ-SIMD-003, REQ-MEM-001/002.
5. Bitmap word access and movemask idioms¶
Bitmaps are byte streams (REQ-MEM-006); backends assemble/consume 64-bit words via memcpy for full words and byte ops for tails. Per-ISA mask movement (normative technique selection):
| ISA | vector-compare → bitmap | bitmap → lane mask |
|---|---|---|
| AVX2 | vpmovmskb (+ width squeeze for 16/32/64-bit lanes) |
byte → LUT expansion or vpbroadcast+vpand+vpcmpeq bit test |
| NEON | shrn narrowing idiom (no movemask instruction; Survey §4.1) |
TBL bit-spread + cmtst |
| AVX-512 | native k-register → kmov store |
kmov load → masked ops directly |
| scalar | shift-OR byte assembly | shift-AND bit test |
6. Compaction machinery (shared, REQ-SIMD-005)¶
The emulated-compress core used by K2 and K3 (and K1's selvec forms) on pre-AVX-512 ISAs: per input byte of selection bitmap, LUT lookup yields lane-permutation indices; permute; store; advance output pointer by popcount(byte). This is the field-standard technique (Survey §4.1, §4.3 — simdprune lineage). AVX-512 replaces it wholesale with vpcompress* (register-form + separate store; Zen 4 hazard note is normative in 08 K2). Write-bound argument (REQ-MEM-008): each full-vector store lands at output cursor c ≤ inputs-processed-so-far, so every byte written lies within the n-element capacity region; input tails follow ADR-015. Guard-page tests sit at the capacity boundary and therefore pass by construction, not by luck.
7. Per-ISA engineering notes (normative constraints for implementers)¶
| ISA | Constraints and facts the implementation shall respect |
|---|---|
| Scalar | Portable C++23 only; shaped for auto-vectorization (contiguous, fixed-trip inner loops, no aliasing via QUIVER_RESTRICT where legal per ADR-023) — it doubles as the honest baseline (ADR-011) and the semantic spec (T3). |
| AVX2 | Two 128-bit lane halves: prefer in-lane shuffles; lane-crossing permutes (vpermd) cost ~3 cyc (Survey §4.1) — budget them once per 8 elements in compaction. No unsigned compares (bias-XOR synthesis); no 64-bit vector multiply (3×vpmuludq decomposition). Shuffle port is the scarce resource in compaction loops (Survey §4.1). |
| NEON | Fixed 128-bit; no gather (Survey §4.1) — K5 stays scalar-load based; movemask via shrn; ≥4-wide unrolling (REQ-SIMD-008); prefer TBL for byte shuffles. |
| AVX-512 | Masks are the product: compress, masked tails, vpcmpu*. Compress-to-register-then-store on all µarchs (Zen 4 microcoded compress-to-memory — Survey §4.1). 512-bit datapath assumed benign on Ice-Lake+/Zen 4+ (Survey §4.1); no frequency-license mitigation logic in v1 — dispatch never selects AVX-512 on µarchs that lack it, and license-era CPUs (Skylake-X) simply get AVX2 unless the integrator overrides. |
8. Failure modes¶
Illegal-instruction crashes are structurally prevented: ISA code is reachable only through dispatch entries gated by MOD-CPU detection (REQ-DISP-001..004); the only bypass is detail:: symbol abuse, which is documented as unsupported (REQ-API-007). A target-region compile failure on tier-1 toolchains is a build defect (03 §8).
9. Test and benchmark obligations¶
Guard-page tail tests per kernel × ISA (REQ-SIMD-003); LUT re-derivation (05 §6); cross-ISA differential equality (12 §2, REQ-TEST-003); per-ISA throughput grids and autovec-vs-explicit verdicts (10/11); -Rpass-missed nightly artifact (REQ-SIMD-009).
10. Acceptance criteria¶
REQ-SIMD-001..010 verified (lints, guard-page suites, LUT tests, SDE runs); every backend TU builds warning-clean on tier-1 toolchains with no global ISA flags; amalgamated build produces byte-identical kernel outputs (REQ-BUILD-013).
11. Traceability¶
Charter §6.3, §4 (first-party per-ISA decision), §7.2 → REQ-SIMD-001..010 → ADR-003/015 (here), ADR-011 (10), ADR-018 (03) → kernel algorithms (08 §5) → milestones M4 (AVX2), M5 (NEON), M7 (AVX-512). Survey authority: §3.1, §3.9, §4.1–§4.5.