Skip to content

oracle: repair the run script, then use it — chacha20 reach and the BLAKE3 shuffle gap - #265

Merged
AdaWorldAPI merged 4 commits into
masterfrom
claude/oracle-run-repair
Jul 29, 2026
Merged

oracle: repair the run script, then use it — chacha20 reach and the BLAKE3 shuffle gap#265
AdaWorldAPI merged 4 commits into
masterfrom
claude/oracle-run-repair

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Three commits, docs and tooling only. The first repairs the oracle; the second and third use it.

1 — repair the run script broken by the relocation

#264 moved the codegen oracle from crates/simd-codegen-oracle/ + scripts/ into .claude/knowledge/simd-codegen-oracle/. The relocation rewrote the prose references but not the script's own path arithmetic, so the tool merged unusable: ROOT resolved one .. short of the repo root, MANIFEST pointed at a Cargo.toml the same PR deleted, and the analyzer path pointed at scripts/.

run.sh is now self-contained — it derives the repo root from its own location, materializes a throwaway crate from probes.rs under $TMPDIR, and cleans up on exit. Two properties are load-bearing and deliberate:

  • cd "$REPO" before cargo, because cargo resolves .cargo/config.toml from the working directory rather than from --manifest-path.
  • -C target-cpu declared on the final rustc invocation, unchanged from blake3: drop the C toolchain requirement; record measured u32/u64 lane codegen #264. Cargo's RUSTFLAGS replaces [target.'cfg(…)'].rustflags rather than merging, so a tool that inherits its baseline measures a different machine depending on where it runs — the exact failure that made the earlier CI attempt report packed = 0 for every probe.

Two docs carried the same damage and are fixed: README.md's run section was the pre-move manual recipe with placeholder paths, and simd-one-spec-design.md had a shell block whose commands were the literal text see .../README.md, with a stray bullet from "What this buys" stranded beneath it.

2 — what vendor/chacha20 actually reaches

Three manifests describe the vendored tree as accelerating consumers' XChaCha20-Poly1305 keystreams. Measured, it reaches less than that, along two axes that had been conflated.

Patch reach. [patch.crates-io] applies only from a top-level workspace manifest, so ndarray's patch does not travel with ndarray. Two repos link the vendored source — ndarray itself (Cargo.lock carries chacha20 0.9.1 with no source line) and MedCare-rs, which declares its own. lance-graph, OGAR, tesseract-rs, stockfish-rs and a2ui-rs link the registry crate.

Backend reach. The added ndarray_simd backend is gated on the compile-time avx512f feature cfg. The workspace pins x86-64-v3, which supplies avx2 and not avx512f; MedCare-rs pins nothing at all. So no default build of any repo here compiles that backend — only an opt-in v4 build or wasm32+simd128 does. The fallthrough to RustCrypto's own backends is correct, and MedCare's comment describes it accurately; the scope simply keeps being restated one size too large.

The audit also records that AdaWorldAPI/stream-ciphers — the fork the P0 rule names — is a single-commit mirror of upstream at chacha20 0.10.1 carrying no AdaWorldAPI delta and no ndarray backend, while the vendored tree is a hand copy of 0.9.1 with its repository field rewritten. The two are a cipher major apart, and upstream 0.10.1 now ships its own avx512 backend in the niche ndarray_simd was written to fill.

One inaccuracy is recorded, not fixed: the root manifest attributes target-cpu=x86-64-v4 to the workspace, which pins v3. Manifest string edits need a ruling, so the finding is filed rather than applied. Three questions are left explicitly open for that ruling.

3 — the BLAKE3 shuffle gap, measured

With C removed from blake3 (features = ["pure"], shipped in #264), what remains is a second SIMD surface: 2,910 lines of raw core::arch across its Rust backends. The question is what a ndarray::simd-native backend would need.

Census: rust_avx2.rs uses 15 distinct intrinsics. Twelve are already expressible on U32x16. The other three families — unpacklo/unpackhi_epi32, unpacklo/unpackhi_epi64, permute2x128, 18 call sites — exist solely to build hash_many's transpose, and U32x16 has no shuffle surface at all.

Rather than assume that means intrinsics (the assumption TD-T22 already falsified once, at the cost of a 700-line PR), four probes:

probe packed scalar on lane data emitted
blake3_g_u32x16 72 0 vpshufb for rotr 16/8, shift-or for rotr 12/7
interleave_lo_u32x16 11 0 vpermd + vpblendd
transpose_16x16_u32 0 1 1088 B stack, 256-iteration scalar copy
transpose_stage_u32x16 27 0 vunpcklps / vunpckhps

The compression core is free today, so compress_in_place and compress_xof are a transcription. The interleave primitive is free too — a plain scalar index loop compiles to a genuine two-source cross-lane permute, which extends cross_lane_reverse_u8x64's earlier single-source result to the half that was still open.

What fails is only the monolithic index-loop spelling of the transpose, where the stride-64 scatter defeats the vectorizer. The last two rows are the same transpose; composed from interleave calls it emits literally the unpack family the intrinsic backend hand-writes.

So no intrinsic override is earned under simd-one-spec-design.md's entry criterion. The gap is a method surface on U32x16 — five interleave/permute methods, each a scalar index loop, no unsafe and no core::arch — with the transpose written as a composition of them.

The findings doc states its scope limits plainly: degree 16 rather than 8 (per the U32x8 ruling); the staged probe measures codegen shape, not transpose correctness; x86_64 only; and no throughput benchmark — "emits packed shuffles" is not "beats rust_avx2.rs", and that comparison has not been run.

Verification

$ sh .claude/knowledge/simd-codegen-oracle/run.sh
==> baseline: x86_64-unknown-linux-gnu @ target-cpu=x86-64-v3 (declared, not inherited)
...
simd-codegen-oracle: ALL PROBES MATCH BASELINE EXPECTATIONS

17/17 probes, including the four new Group D rows. No product code is touched — the whole PR is under .claude/knowledge/.

Summary by CodeRabbit

  • Documentation

    • Added guidance on portable BLAKE3 SIMD implementation constraints and measured vectorization behavior.
    • Documented the build impact and target-specific behavior of the vendored ChaCha20 implementation.
    • Updated SIMD design guidance with clearer performance expectations and oracle usage instructions.
  • Tools

    • Simplified SIMD code-generation checks with an automated temporary build workflow.
    • Added host and cross-target execution examples, verbose output, and clearer baseline error handling.
    • Expanded reports to cover BLAKE3 mixing, interleaving, and transpose vectorization results.

The move from crates/ + scripts/ into .claude/knowledge/ (#264) rewrote
the doc references but not the script's own path arithmetic. As merged,
run.sh resolved ROOT to .claude/knowledge/ and pointed at
crates/simd-codegen-oracle/Cargo.toml and
scripts/codegen_oracle_analyze.py -- neither of which exists. The tool
shipped unusable.

run.sh is now self-contained: it derives the repo root from its own
location, materializes a throwaway crate from probes.rs under TMPDIR,
cds into the repo before invoking cargo (config.toml resolves from the
working directory, not from --manifest-path), and removes the scratch
tree on exit. The declared -C target-cpu baseline is unchanged and still
lands on the final rustc invocation, so ambient RUSTFLAGS cannot drop it.

Verified end to end: 13/13 probes match baseline-x86_64-v3.toml.

Also repaired two doc casualties of the same relocation: the README's
run instructions were the pre-move manual recipe with placeholder paths,
and simd-one-spec-design.md had a shell block whose commands were the
literal text "see .../README.md", with a stray "What this buys" bullet
stranded beneath it.
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@AdaWorldAPI, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c19a8dd5-7c87-4a0a-87ad-5e943ef4a7d3

📥 Commits

Reviewing files that changed from the base of the PR and between 3e72c5d and 3c427ae.

📒 Files selected for processing (6)
  • .claude/knowledge/blake3-on-ndarray-simd.md
  • .claude/knowledge/chacha20-vendoring-blast-radius.md
  • .claude/knowledge/simd-codegen-oracle/baseline-x86_64-v3.toml
  • .claude/knowledge/simd-codegen-oracle/probes.rs
  • .claude/knowledge/simd-codegen-oracle/run.sh
  • .claude/knowledge/simd-one-spec-design.md
📝 Walkthrough

Walkthrough

The PR adds BLAKE3 SIMD codegen probes, rewrites the SIMD oracle runner around temporary crates and target baselines, updates related usage documentation, and adds measured knowledge documents covering BLAKE3 portability and ChaCha20 vendoring reach.

Changes

SIMD oracle and BLAKE3 analysis

Layer / File(s) Summary
Scratch-build oracle workflow
.claude/knowledge/simd-codegen-oracle/run.sh, .claude/knowledge/simd-codegen-oracle/README.md, .claude/knowledge/simd-one-spec-design.md
The oracle now creates a temporary crate, selects target baselines, emits assembly, runs analysis, cleans up, and documents host and cross-target commands.
BLAKE3 and transpose probes
.claude/knowledge/simd-codegen-oracle/probes.rs, .claude/knowledge/simd-codegen-oracle/baseline-x86_64-v3.toml
Group D adds BLAKE3 mixing, interleave, full-transpose, and staged-transpose probes with corresponding measured baseline entries and checksum integration.
Measured SIMD backend findings
.claude/knowledge/blake3-on-ndarray-simd.md
The document records vectorization measurements, missing U32x16 shuffle methods, scope limits, and remaining design questions.

ChaCha20 vendoring reach

Layer / File(s) Summary
Vendored backend reach analysis
.claude/knowledge/chacha20-vendoring-blast-radius.md
The document distinguishes patch reach from backend compilation reach, records target-configuration outcomes, compares vendored and forked trees, and lists unresolved operator decisions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: claude

Poem

A bunny hops through lanes of light,
While shuffles bloom from left to right.
Scratch crates spin, baselines sing,
Transposes test each folded wing.
Docs record what probes reveal—
Soft paws guard the SIMD wheel.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main changes: repairing the oracle run script and documenting chacha20 reach plus the BLAKE3 shuffle gap.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a586774f-2e8b-4f48-98ad-b16cdedb3e7a)

The vendored chacha20 tree is described in three manifests as accelerating
consumers' XChaCha20-Poly1305 keystreams. Measured, it reaches far less
than that, along two independent axes that had been conflated.

Patch reach: [patch.crates-io] applies only from a top-level workspace
manifest, so ndarray's patch does not travel with ndarray. Two repos link
the vendored source -- ndarray itself and MedCare-rs, which declares its
own. lance-graph, OGAR, tesseract-rs, stockfish-rs and a2ui-rs link the
registry crate.

Backend reach: the added ndarray_simd backend is gated on the compile-time
avx512f feature cfg. The workspace pins x86-64-v3, which supplies avx2 and
not avx512f, and MedCare-rs pins nothing at all. So no default build of any
repo here compiles that backend -- only an opt-in v4 build or wasm32+simd128
does. The fallthrough to RustCrypto's own backends is correct and MedCare's
comment describes it accurately; the scope simply keeps being restated one
size too large.

Also records that AdaWorldAPI/stream-ciphers -- the fork the P0 rule names --
is a single-commit mirror of upstream at chacha20 0.10.1 carrying no
AdaWorldAPI delta and no ndarray backend, while the vendored tree is a hand
copy of 0.9.1 with its repository field rewritten. The two are a cipher
major apart, and upstream 0.10.1 now ships its own avx512 backend in the
niche ndarray_simd was written to fill.

One inaccuracy is recorded, not fixed: the root manifest attributes
target-cpu=x86-64-v4 to the workspace, which pins v3. Manifest string edits
need a ruling, so the finding is filed instead of applied.

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Draft is intentional (repo default for agent-opened PRs), but this is docs-and-tooling only and a review is welcome. Since the last push the PR also carries a second commit: a measurement audit of what vendor/chacha20 actually reaches.

Worth pointing the review at two things specifically:

  1. run.sh's path arithmetic and its cd. The script derives the repo root from its own location and cds there before invoking cargo — deliberately, because cargo resolves .cargo/config.toml from the working directory rather than from --manifest-path. It also passes -C target-cpu after the -- so it lands on the final rustc invocation, which is what makes the baseline survive an ambient RUSTFLAGS (cargo's RUSTFLAGS replaces [target.'cfg(…)'].rustflags rather than merging with it).

  2. The factual claims in chacha20-vendoring-blast-radius.md. Each row is sourced from Cargo.lock, a rustc --print cfg, or a manifest on disk, and the conclusion is narrowing rather than expanding — the patch reaches two repos, not seven, and the added backend compiles on no default build at all. If any row reads as overstated, or as resting on an inference rather than a check, that is the most useful thing to flag.


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@AdaWorldAPI I’ll review the docs/tooling changes, with particular attention to run.sh’s repository-root/configuration behavior and the evidence supporting each blast-radius claim.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Answers "what is missing to express BLAKE3 on ndarray::simd instead of raw
intrinsics" with four probes rather than with intuition.

Census first: BLAKE3's pure-Rust AVX2 backend uses 15 distinct intrinsics.
Twelve are already expressible on U32x16 -- add, xor, or, the shift pair
inside rotate_left, splat, set, load, store. The other three families
(unpacklo/hi_epi32, unpacklo/hi_epi64, permute2x128 -- 18 call sites) exist
solely to build hash_many's transpose, and U32x16 has no shuffle surface at
all.

Measured, at x86-64-v3:

  blake3_g_u32x16          72 packed /  0 scalar   rotr16,rotr8 -> vpshufb;
                                                   rotr12,rotr7 -> shift-or
  interleave_lo_u32x16     11 packed /  0 scalar   vpermd + vpblendd
  transpose_16x16_u32       0 packed / 47 memory   1088B stack, 256-iter copy
  transpose_stage_u32x16   27 packed /  0 scalar   vunpcklps / vunpckhps

The compression core is free today. The interleave primitive is also free --
a plain scalar index loop compiles to a genuine two-source cross-lane
permute, extending cross_lane_reverse_u8x64's single-source result. What
fails is only the monolithic nested-index-loop spelling of the transpose,
where the stride-64 scatter defeats the vectorizer; the same transpose
composed from interleave calls emits literally the unpack family the
intrinsic backend hand-writes.

So no intrinsic override is earned under simd-one-spec-design.md's entry
criterion. The gap is a method surface on U32x16 -- five interleave/permute
methods, each a scalar index loop, no unsafe and no core::arch -- with the
transpose written as a composition of them rather than as an index loop.

Findings doc records the census, the four measurements, the scope limits
(degree 16 not 8; codegen shape not transpose correctness; x86_64 only; no
throughput benchmark) and the three questions still open.
@AdaWorldAPI AdaWorldAPI changed the title oracle: repair the run script and docs broken by the relocation oracle: repair the run script, then use it — chacha20 reach and the BLAKE3 shuffle gap Jul 29, 2026
@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review July 29, 2026 06:43

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Retrying past the rate limit. The PR is out of draft now, so this should be the last manual trigger.


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@AdaWorldAPI I’ll review PR #265, focusing on the oracle script’s path/configuration behavior and the evidence behind the Chacha20 blast-radius audit.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e72c5d525

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +50 to +51
[dependencies]
ndarray = { path = "$REPO", default-features = false, features = ["std"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the scratch crate on the workspace lockfile

When the checkout is used in an offline or minimally cached environment, this independent scratch package has no lockfile, so Cargo attempts to update the crates.io index before compiling; running the documented command here failed while resolving blake3, despite the repository already having a committed Cargo.lock. This also lets dependency resolution drift between oracle runs, so the scratch build should reuse the repository's locked dependency graph rather than resolving afresh.

Useful? React with 👍 / 👎.

Comment on lines +30 to +32
case "$TARGET" in
x86_64-*) BASELINE="$HERE/baseline-x86_64-v3.toml"; CPU="x86-64-v3" ;;
*) BASELINE="$HERE/baseline-$TARGET.toml"; CPU="" ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject x86 targets without a matching baseline

For any cross-target whose triple starts with x86_64-—for example x86_64-pc-windows-msvc—this branch silently selects the Linux-host baseline-x86_64-v3.toml instead of requiring baseline-<triple>.toml as the README promises. Target-specific assembly syntax, ABI instructions, and counts can therefore produce meaningless comparisons or missing-symbol failures; only the target for which this baseline was measured should select it, and other triples should require their own baseline.

Useful? React with 👍 / 👎.

Comment on lines +113 to +116
### …but the composed transpose is

Same transpose, expressed as eight pairwise interleave calls per butterfly
stage: **27 packed, and the instructions are `vunpcklps` / `vunpckhps`** —

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Measure a complete correct transpose before closing the gap

For a future BLAKE3 backend relying on this result, the 27-instruction probe is not the “same transpose”: transpose_stage_u32x16 executes only one 32-bit interleave stage, and its own documentation acknowledges that repeating these helpers does not produce a correct transpose. It also never exercises the required 64-bit interleaves or 128-bit half permutation, so the measurement cannot establish that the complete composition stays packed or justify the subsequent “no intrinsic is earned” conclusion; a correct full transpose using all required primitive shapes needs to be probed.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/knowledge/chacha20-vendoring-blast-radius.md:
- Around line 3-4: The audit’s evidence provenance is incomplete: update the
opening status statement in .claude/knowledge/chacha20-vendoring-blast-radius.md
lines 3-4 to either include Git/source-tree comparisons or narrow the listed
sources to Cargo.lock, manifests, and rustc cfg output; update lines 127-129 to
record the exact upstream commit/tree hash or a reproducible diff supporting the
“same bytes” conclusion, rather than relying only on a head commit and branch
count.
- Around line 69-74: Specify a language identifier on the fenced code block
containing the rustc commands, using console or text, while preserving its
command output and explanatory comment.

In @.claude/knowledge/simd-codegen-oracle/probes.rs:
- Around line 416-424: The current probe does not validate the complete BLAKE3
degree-16 transpose. In .claude/knowledge/simd-codegen-oracle/probes.rs:416-424,
replace or extend transpose_stage_u32x16 with a semantically correct full
transpose network, including required u64 interleave and half-permutation
stages, and verify it against a scalar reference. In
.claude/knowledge/simd-codegen-oracle/baseline-x86_64-v3.toml:148-154, restrict
conclusions to the measured non-semantic stage until that probe exists. In
.claude/knowledge/blake3-on-ndarray-simd.md:113-142, qualify the “no intrinsic
is earned” conclusion and proposed method surface as pending validation of the
complete transpose network.

In @.claude/knowledge/simd-codegen-oracle/run.sh:
- Around line 40-42: Replace the predictable SCRATCH path and separate mkdir -p
setup with an atomic mktemp -d allocation, preserving the existing cleanup trap
and ensuring the required src subdirectory is created only after the unique
scratch directory exists.
- Around line 81-93: Update both cargo rustc invocations in the build logic
around the host and cross-target branches to explicitly set Cargo’s target
directory to $SCRATCH/target. Preserve the existing release, manifest, target,
and assembly-emission options while ensuring artifacts are always written under
the scratch tree for ASM discovery and cleanup.

In @.claude/knowledge/simd-one-spec-design.md:
- Around line 196-197: Update the command examples in the SIMD codegen oracle
documentation so the aarch64 invocation is clearly marked as a post-baseline
example or remove it; retain the runnable x86-64-v3 command and do not present
aarch64 as currently supported while no aarch64 baseline exists.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dd44f880-81c4-4d48-b50f-c31c7a2a8fce

📥 Commits

Reviewing files that changed from the base of the PR and between 8a07459 and 3e72c5d.

📒 Files selected for processing (7)
  • .claude/knowledge/blake3-on-ndarray-simd.md
  • .claude/knowledge/chacha20-vendoring-blast-radius.md
  • .claude/knowledge/simd-codegen-oracle/README.md
  • .claude/knowledge/simd-codegen-oracle/baseline-x86_64-v3.toml
  • .claude/knowledge/simd-codegen-oracle/probes.rs
  • .claude/knowledge/simd-codegen-oracle/run.sh
  • .claude/knowledge/simd-one-spec-design.md

Comment thread .claude/knowledge/chacha20-vendoring-blast-radius.md Outdated
Comment thread .claude/knowledge/chacha20-vendoring-blast-radius.md Outdated
Comment thread .claude/knowledge/simd-codegen-oracle/probes.rs
Comment thread .claude/knowledge/simd-codegen-oracle/run.sh Outdated
Comment thread .claude/knowledge/simd-codegen-oracle/run.sh
Comment thread .claude/knowledge/simd-one-spec-design.md Outdated
Six review findings from codex and coderabbit on #265. Five are fixes; one
was a real methodological error on my part.

THE SUBSTANTIVE ONE. The BLAKE3 conclusion rested on transpose_stage_u32x16,
which is ONE 32-bit butterfly stage whose whole-vector helper semantics do
not compose into a real transpose -- it never exercised the 64-bit unpack or
the 128/256-bit permutes, so "the composed transpose stays packed" was an
inference wearing a measurement's clothes. Exactly the failure mode TD-T22
exists to prevent, committed in the document that cites TD-T22.

Fixed by measuring it. transpose_16x16_composed is a complete 16x16 transpose
built from a const-generic exchange<G> at G = 1/2/4/8, so all four
granularities appear. Measured 79 packed / 0 scalar on lane data, of which 19
are real shuffles: vinserti128 x7, vpshufd x3, vpblendd x3, vpunpcklqdq x2,
vpermq x2, vunpcklpd, vpermpd. The conclusion survives, now on evidence.

Correctness is checked rather than claimed: the driver compares against a
naive nested-loop transpose and aborts on mismatch, and run.sh now EXECUTES
the probe binary, because --emit asm links nothing and the assertion would
otherwise never have run -- a claim of verification that does not verify is
the same defect one level up. Control-tested by deleting stage::<8>, which
makes it fire (exit 101).

Two caveats added rather than smoothed over: the composed form is not clean
straight-line code (38 loop-control, 41 memory spill, since sixteen 512-bit
vectors are 32 ymm registers against 16 architectural ones -- a hand-written
backend faces the same), and none of this is a throughput comparison against
rust_avx2.rs.

run.sh hardening:
- mktemp -d instead of a PID-derived path; mkdir -p accepts an existing
  directory, so a predictable name lets a local attacker pre-create it with
  symlinked children and redirect the cp and heredoc writes.
- --target-dir pinned to the scratch tree, so an ambient CARGO_TARGET_DIR
  cannot put artifacts where the asm discovery and the cleanup will not find
  them.
- Baseline selection is exact-triple, not an x86_64-* glob that silently
  handed x86_64-pc-windows-msvc the Linux baseline. Verified: that triple now
  exits 90 with a message saying there is deliberately no family fallback.
- The repository Cargo.lock is copied into the scratch crate and the build
  tries --offline first. A fresh scratch package otherwise hits the crates.io
  index before compiling anything, which fails on a cold cache, and lets two
  oracle runs measure two different dependency graphs -- unacceptable in an
  instrument whose whole job is reproducibility.

Docs:
- The chacha20 audit's "fork and upstream are the same bytes" line was
  inferred from a head commit and a branch count. Replaced with the actual
  check against RustCrypto/stream-ciphers: identical head sha, zero commits
  ahead, identical chacha20/ tree hash -- and git tree hashes cover content
  recursively, so that is byte equality. Provenance line widened to name git
  object hashes as a source, and a fenced block got a language tag.
- The aarch64 invocation in simd-one-spec-design.md was presented as runnable
  when no aarch64 baseline exists and it exits 90; now marked as pending that
  baseline, which is step 2 of the migration.

17 probes green; scratch cleanup verified.

Copy link
Copy Markdown
Owner Author

All six findings addressed in 3c427ae. Taking the most important one first, because it was a real methodological error and not a nit.

The transpose measurement (codex P2, coderabbit 🟠 Major)

Both reviews caught the same thing and both were right: the BLAKE3 conclusion rested on transpose_stage_u32x16, which is one 32-bit butterfly stage whose whole-vector helper semantics do not compose into a real transpose. It exercised neither the 64-bit unpack nor the 128/256-bit permutes. "The composed transpose stays packed" was an inference wearing a measurement's clothes — precisely the failure mode TD-T22 exists to prevent, committed in the document that cites TD-T22.

The fix is to measure it rather than to hedge the wording. transpose_16x16_composed is a complete 16×16 transpose built from a const-generic exchange<G> at G = 1/2/4/8, so all four granularities are present:

probe packed scalar on lane data emitted
transpose_16x16_u32 (index loop) 0 1 1088 B stack, 256-iteration scalar copy
transpose_16x16_composed 79 0 60 moves + 19 shuffles: vinserti128 ×7, vpshufd ×3, vpblendd ×3, vpunpcklqdq ×2, vpermq ×2, vunpcklpd, vpermpd

The conclusion survives, now on evidence. vpunpcklqdq is the 64-bit unpack and vpermq/vpermpd are the cross-lane permutes that the previous probe never reached.

Correctness is now checked rather than claimed. The driver compares the result against a naive nested-loop transpose and aborts on mismatch — and run.sh now executes the probe binary, because --emit asm links nothing and that assertion would otherwise never have run. A claim of verification that does not verify is the same defect one level up, so it was worth catching. Control-tested by deleting stage::<8>: the assertion fires, exit 101.

Two caveats are stated in the doc rather than smoothed over. The composed form is not clean straight-line code — 38 loop-control instructions and 41 memory ops of real spill traffic, because sixteen 512-bit vectors of live state are 32 ymm registers against 16 architectural ones. A hand-written intrinsic backend faces exactly the same pressure. And none of this is a throughput comparison against rust_avx2.rs; that benchmark has not been run and is listed as open.

run.sh (coderabbit 🟠 ×2, codex P2)

  • mktemp -d instead of the PID-derived path. mkdir -p accepts an existing directory, so a predictable name lets a local attacker pre-create it with symlinked children and redirect the cp and heredoc writes.
  • --target-dir pinned to the scratch tree, so an ambient CARGO_TARGET_DIR cannot put artifacts where the asm discovery and the cleanup won't find them.
  • Exact-triple baseline selection. The x86_64-* glob silently handed x86_64-pc-windows-msvc the Linux baseline. Verified after the fix:
    $ sh run.sh x86_64-pc-windows-msvc
    ==> no baseline for x86_64-pc-windows-msvc at .../baseline-x86_64-pc-windows-msvc.toml
        A baseline is per-TRIPLE; there is deliberately no family fallback.
  • The repository Cargo.lock is copied into the scratch crate, and the build tries --offline first. Both halves of that finding are real: a fresh scratch package hits the crates.io index before compiling anything, which fails on a cold cache, and resolving afresh lets two oracle runs measure two different dependency graphs — unacceptable in an instrument whose entire job is reproducibility.

Docs

The "fork and upstream are the same bytes" line was inferred from a head commit and a branch count, which coderabbit correctly called insufficient. Replaced with the actual check against RustCrypto/stream-ciphers:

$ git rev-parse HEAD upstream/master
5f3430b7531a33aa14957b6bd407b46687635124
5f3430b7531a33aa14957b6bd407b46687635124
$ git rev-list --count upstream/master..HEAD
0
$ git rev-parse HEAD:chacha20 upstream/master:chacha20
3f58304be34b79a3a38430a5752fb8db223d1a20
3f58304be34b79a3a38430a5752fb8db223d1a20

Git tree hashes cover content recursively, so identical tree ids are byte equality for that directory. The provenance line now names git object hashes as a source alongside Cargo.lock, manifests and rustc --print cfg, and the fenced block got a console tag (MD040).

The aarch64 invocation in simd-one-spec-design.md was shown as runnable when no aarch64 baseline exists and it exits 90 — now marked as pending that baseline, which is step 2 of the migration the same document describes.

17 probes green, scratch cleanup verified, no product code touched.


Generated by Claude Code

@AdaWorldAPI
AdaWorldAPI merged commit 58521c3 into master Jul 29, 2026
19 checks passed
AdaWorldAPI added a commit that referenced this pull request Jul 29, 2026
docs: settle what actually compiles vendor/chacha20; board hygiene for #264/#265
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants