Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .claude/knowledge/agnostic-surface-cpu-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,40 @@ verifies that no per-CPU regression has crept in vs the historical baseline:

## M. AArch64 ground-truth core enumeration (GCC source)

> **Scope correction (appended 2026-07-27, operator-stated).** The heading and
> the "authoritative" wording below overstate GCC's role. **GCC is the fill-in
> for what we could not execute**; everything reachable was verified by running
> it. Two distinct mechanisms, not to be conflated:
>
> - **Validation (what the lanes compute):** `scripts/neon-parity.sh` cross-builds
> `crates/neon-simd-parity` for `aarch64-unknown-linux-gnu` and runs it under
> `qemu-aarch64-static`, asserting the exercised lanes are bit-identical to
> their scalar reference; `scripts/wasm-parity.sh` is the wasm32+simd128 twin
> under node. **Coverage as of 2026-07-28 (from `selfcheck` in
> `crates/neon-simd-parity/src/main.rs`, not the full export surface):**
> `U32x16` (Add / BitXor / rotate_left — the ChaCha20/BLAKE ARX triple),
> `F32x16` (splat / roundtrip / add / reduce_sum), `I8x16` (roundtrip / add).
> Exported lanes NOT yet exercised there (e.g. `I16x8`, `U8x16`, `U64x2`) are
> **unverified by this harness** — a later SIMD audit must not treat them as
> measured; extending `selfcheck` is the way to promote one. Within its
> coverage these runs are the measurement of record for lane arithmetic — and
> they need **no physical silicon**, which is why the aarch64 surface could be
> measured at all.
> - **Runtime detection (what a given CPU admits to having):**
> `sysctl hw.optional.arm.FEAT_*` on Darwin / `getauxval(AT_HWCAP)` on
> Linux/Android (`src/simd_neon_dotprod.rs:29-30`), `__cpuid_count` on x86
> (`src/simd_caps.rs:160-167`).
>
> GCC's role is the third thing neither of those gives you: **which shipping core
> carries which feature.** Emulation proves an instruction works; it cannot tell
> you that `cortex-a76` has DOTPROD and `cortex-a72` does not. Read the table
> below as *GCC's declared per-core feature membership* — authoritative for
> untestable parts, corroborating elsewhere.
>
> The URL cited at the end of this section points at mutable `master`; pin a
> commit when re-scraping (see `.claude/knowledge/gcc-intrinsic-spec-reference.md`,
> which also documents the intrinsic-semantics layers of the same source).

The matrix above uses three aarch64 columns (A53 / A72 / A76) that
each cover a *dispatch tier* — multiple physical cores share the same
SIMD primitive set. The authoritative per-core feature membership is
Expand Down
113 changes: 113 additions & 0 deletions .claude/knowledge/gcc-intrinsic-spec-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# GCC as the intrinsic-spec reference — the three-layer drill-down

> READ BY: anyone verifying what an intrinsic actually *does* before writing or
> porting a SIMD kernel — `simd-savant`, `arm-neon-specialist`, and any session
> touching `src/simd_*.rs`, the polyfill matryoshka, or a consumer-crate SIMD
> swap.
>
> **Why this file exists:** the reference below was used across the NEON /
> aarch64 / wasm planning work but was never written down. A 2026-07-27 sweep of
> every URL host in every `.md` / `.rs` / `.toml` in this repo found no
> intrinsic or ISA reference of any kind — the only spec-shaped citations were
> four bare "Intel Intrinsics Guide" mentions with no link
> (`vertical-simd-consumer-contract.md`) and one GCC file fetched off mutable
> `master` (`agnostic-surface-cpu-matrix.md` §M). The link existed only in
> session context. Recording it so it survives the session that knew it.

## The source

**`github.com/gcc-mirror/gcc`** — mirror of `gcc.gnu.org`. Pin a commit; never
cite `master` (a spec citation that moves under you is not a citation).

Working pin used for the 2026-07-27 verification:
`8f1698229d33a74cda7ec9f02575172df10b2774`

```
https://raw.githubusercontent.com/gcc-mirror/gcc/<SHA>/<path>
```

## The three layers — each answers a different question

| layer | path | answers |
|---|---|---|
| **1. declarations** | `gcc/config/i386/*intrin.h`<br>`gcc/config/aarch64/arm_neon.h` | *What builtin does this intrinsic map to, and what are its exact C types?* |
| **2. machine description** | `gcc/config/*/*.md` | *What instruction / RTL does that builtin lower to, and what are the bit encodings?* |
| **3. conformance tests** | `gcc/testsuite/gcc.target/{i386,aarch64,arm,...}/` | *What does it compute?* — **where a runtime test exists**, an executable check with an **inline scalar reference implementation** |

Layer 3 is the one people don't know about and is the most useful **when it
applies** — but qualify the claim: `gcc.target` mixes runtime tests with
compile-only, diagnostic, and codegen (`scan-assembler`) tests, and not every
intrinsic has a runtime test with a scalar reference. The discriminator is the
DejaGnu directive: `dg-do run` (executable) vs `dg-do compile` / `dg-do
assemble` (no semantic validation). Where a `dg-do run` test with a scalar
loop + `abort()`-style comparison exists, it is a per-intrinsic **oracle**,
not prose — directly usable for the byte-parity discipline this workspace
already applies elsewhere (tesseract-rs, stockfish-rs): port a kernel, then
prove it against GCC's own definition of what the instruction computes rather
than a hand-written reference. Where only a compile/scan test exists, layer 3
proves nothing about semantics — fall back to the ISA specification (Intel
SDM / Arm ARM) as the authority, with layers 1-2 still pinning types and
lowering.

## Worked example — the question that motivated this file

`_mm256_mul_epu32` vs `_mm256_mul_epi32`, needed for a `curve25519-dalek`
SIMD swap onto `ndarray::simd`.

**Layer 1** (`gcc/config/i386/avx2intrin.h`):

```c
_mm256_mul_epi32 (__m256i __X, __m256i __Y)
{ return (__m256i) __builtin_ia32_pmuldq256 ((__v8si)__X, (__v8si)__Y); }

_mm256_mul_epu32 (__m256i __A, __m256i __B)
{ return (__m256i) __builtin_ia32_pmuludq256 ((__v8si)__A, (__v8si)__B); }
```

Both take `__v8si` and return `__m256i` — **identical C signatures**. The
signed/unsigned distinction lives entirely in the instruction (VPMULDQ vs
VPMULUDQ), not in the type. So the type system will not catch a mix-up here;
only the semantics will.

**Layer 3** (`gcc/testsuite/gcc.target/i386/avx2-vpmuludq-2.c`) gives the
semantics in one line:

```c
for (i = 0; i < 4; i++)
r[i] = s1[i * 2] * s2[i * 2]; /* unsigned int × unsigned int → unsigned long long */
```

i.e. **even 32-bit lanes only** (equivalently: the low 32 bits of each packed
64-bit element), widening to 4 × u64. The odd lanes are ignored entirely.
`avx2-vpmuldq-2.c` sits beside it as the signed twin — the pair is a ready-made
differential oracle.

## Honest limits

- **Test filenames are not guessable.** `avx2-vpmuludq-2.c` and
`avx2-vpermd-1.c` exist; `avx2-vpsrlvd-1.c` does not (that op is tested under
a different name). Get a real directory listing rather than probing guesses.
- **The GitHub *API* is scoped to session repos**, so `gcc-mirror/gcc` cannot be
listed through it from here; `raw.githubusercontent.com` fetches work fine.
- **GitHub *code search* excludes forks** — it silently returns 0 for files that
demonstrably exist in this org's forked repos. Verified 2026-07-27:
`filename:harvest_network.rs` returned 0 while the file exists at
`AdaWorldAPI/ruff:crates/ruff_cpp_spo/examples/harvest_network.rs`. **Never
treat a code-search miss on a fork as evidence of absence** — clone and grep.
- Layer 3 covers what an intrinsic *computes*. It does not give latency or
throughput; that is a separate question and a separate source.

## Not harvested

There is no baked/harvested copy of this spec set in the workspace. Checked
2026-07-27 by local grep (not code search — see above): `ndarray` (tree +
releases — it has none), `lance-graph` (tree + all 11 releases, which are model
codebooks / corpus / topology data), `ruff` (5 harvest examples, all
Tesseract/Leptonica C++), `curve25519-dalek`. The reference is consulted
directly at a pinned SHA.

Worth noting for anyone who wants one: `ruff_cpp_spo` already walks C++ headers
via libclang and emits SPO manifests, and GCC's `*intrin.h` are plain C headers
of exactly that shape — so a `harvest_intrinsics.rs` producing the full
intrinsic → builtin → instruction table would be an extension of proven
machinery rather than new machinery. Not built; recorded as an option.
10 changes: 10 additions & 0 deletions .claude/knowledge/vertical-simd-consumer-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,16 @@ The `simd-savant` agent on the `lance-graph` side runs PRE-MERGE against every W
- PR #400 (architectural capture commit) — the canonical reference + tech-debt entries

**External references:**

> **Sourcing note (appended 2026-07-27):** the four intrinsic citations below
> were recorded as bare "Intel Intrinsics Guide" mentions with no link. The
> checkable source for intrinsic *semantics* in this workspace is GCC —
> declarations in `gcc/config/i386/*intrin.h`, plus an executable per-intrinsic
> oracle (scalar reference inline) in `gcc/testsuite/gcc.target/i386/`. See
> `.claude/knowledge/gcc-intrinsic-spec-reference.md` for the three-layer
> drill-down and a pinned SHA. Prefer that, at a pinned commit, over an
> unlinked guide reference. Original lines kept verbatim below.

- Intel Intrinsics Guide — `_mm512_abs_epi8` (VPABSB; does NOT saturate `i8::MIN`)
- Intel Intrinsics Guide — `_mm512_min_epu8` (VPMINUB; unsigned-byte minimum, used to clamp the VPABSB result)
- Intel Intrinsics Guide — `_mm512_popcnt_epi64` (VPOPCNTDQ; AVX-512 feature `avx512vpopcntdq`)
Expand Down
Loading