Skip to content

Commit 87b9b4c

Browse files
committed
oracle: repair the run script and docs broken by the relocation
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.
1 parent 605e33a commit 87b9b4c

3 files changed

Lines changed: 84 additions & 103 deletions

File tree

.claude/knowledge/simd-codegen-oracle/README.md

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,18 @@ prevent. Measure during design instead.
2828

2929
## Running it
3030

31-
The tool needs a throwaway crate to compile the probes against `ndarray`:
32-
3331
```sh
34-
cd /path/to/ndarray
35-
mkdir -p /tmp/oracle/src
36-
cp .claude/knowledge/simd-codegen-oracle/probes.rs /tmp/oracle/src/main.rs
37-
cat > /tmp/oracle/Cargo.toml <<'EOF'
38-
[package]
39-
name = "simd-codegen-oracle"
40-
version = "0.0.0"
41-
edition = "2021"
42-
[dependencies]
43-
ndarray = { path = "/path/to/ndarray", features = ["std"] }
44-
[profile.release]
45-
debug = false
46-
EOF
47-
48-
cargo rustc --release --manifest-path /tmp/oracle/Cargo.toml -- \
49-
--emit asm -C debuginfo=0 -C target-cpu=x86-64-v3
50-
python3 .claude/knowledge/simd-codegen-oracle/analyze.py \
51-
"$(ls -t /tmp/oracle/target/release/deps/simd_codegen_oracle-*.s | head -1)" \
52-
.claude/knowledge/simd-codegen-oracle/baseline-x86_64-v3.toml
32+
sh .claude/knowledge/simd-codegen-oracle/run.sh # host, x86-64-v3 baseline
33+
sh .claude/knowledge/simd-codegen-oracle/run.sh <target-triple> # cross-target
34+
sh .claude/knowledge/simd-codegen-oracle/run.sh --verbose # per-probe instruction detail
5335
```
5436

55-
`run.sh` automates this against a crate laid out as above; adjust
56-
`MANIFEST`/`BASELINE` at the top for your scratch location.
37+
No setup: the script locates the ndarray checkout it lives in, builds a
38+
throwaway crate from `probes.rs` under `$TMPDIR`, emits assembly, and hands
39+
the `.s` to `analyze.py`. The scratch tree is removed on exit.
40+
41+
Adding a target means adding a `baseline-<triple>.toml`; the script refuses
42+
to guess and exits 90 if one is missing.
5743

5844
## Two properties that make the result trustworthy
5945

Lines changed: 71 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,100 @@
11
#!/bin/sh
2-
# SIMD codegen oracle -- proves what actually vectorizes (crates/simd-codegen-oracle),
3-
# in both directions: Group A probes must show packed AVX2 instructions, Group B
4-
# probes must show none, Group C probes are reported without a pass/fail verdict
5-
# (the open question this oracle was extended to answer). Mirrors the build/locate
6-
# shape of scripts/neon-parity.sh / scripts/wasm-parity.sh, but the analysis itself
7-
# (instruction classification, baseline comparison) lives in the Python helper
8-
# scripts/codegen_oracle_analyze.py -- see its module docstring for the exact
9-
# packed-vector / scalar-lane-arith / loop-control / memory / other classification
10-
# rules and the documented honesty rule (a loop-counter decl is not lane
11-
# arithmetic).
2+
# SIMD codegen oracle -- measures what actually vectorizes, in both directions:
3+
# Group A probes must show packed SIMD, Group B probes must show none, Group C
4+
# probes are reported without a pass/fail verdict.
125
#
13-
# Usage: scripts/codegen-oracle.sh [target-triple] [-- --verbose]
14-
# target-triple defaults to the host triple (`rustc -vV | grep ^host`).
15-
# Everything after the target is forwarded to the analyzer (e.g. --verbose
16-
# to print the raw instruction list per bucket).
6+
# This is an ON-DEMAND instrument, not a CI job. Run it when a codegen question
7+
# is genuinely open, record the answer in a doc, and stop. See README.md.
8+
#
9+
# Self-contained: builds a throwaway crate from probes.rs against the ndarray
10+
# checkout this file lives in, so nothing needs to exist under crates/.
11+
#
12+
# Usage: sh run.sh [target-triple] [--verbose]
13+
# target-triple defaults to the host triple.
1714
set -eu
1815

19-
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
20-
MANIFEST="$ROOT/crates/simd-codegen-oracle/Cargo.toml"
16+
HERE="$(cd "$(dirname "$0")" && pwd)"
17+
# .claude/knowledge/simd-codegen-oracle -> repo root is three levels up.
18+
REPO="$(cd "$HERE/../../.." && pwd)"
19+
if [ ! -f "$REPO/Cargo.toml" ]; then
20+
echo "==> cannot locate the ndarray repo root from $HERE" >&2
21+
exit 91
22+
fi
2123

2224
TARGET="${1:-}"
2325
case "$TARGET" in
24-
"" | -*)
25-
TARGET="$(rustc -vV | sed -n 's/^host: //p')"
26-
;;
27-
*)
28-
shift
29-
;;
26+
"" | -*) TARGET="$(rustc -vV | sed -n 's/^host: //p')" ;;
27+
*) shift ;;
3028
esac
31-
# Remaining args (an optional `--` and/or analyzer flags like --verbose) forward as-is.
32-
if [ "${1:-}" = "--" ]; then
33-
shift
34-
fi
3529

36-
BASELINE="$ROOT/crates/simd-codegen-oracle/baselines/$TARGET.toml"
30+
case "$TARGET" in
31+
x86_64-*) BASELINE="$HERE/baseline-x86_64-v3.toml"; CPU="x86-64-v3" ;;
32+
*) BASELINE="$HERE/baseline-$TARGET.toml"; CPU="" ;;
33+
esac
3734
if [ ! -f "$BASELINE" ]; then
38-
echo "==> no baseline for target $TARGET at $BASELINE" >&2
35+
echo "==> no baseline for $TARGET at $BASELINE" >&2
36+
echo " (run with --verbose and record the observed counts to make one)" >&2
3937
exit 90
4038
fi
4139

42-
# The measured baseline is DECLARED here, never inherited from the ambient
43-
# environment. This is load-bearing:
40+
SCRATCH="${TMPDIR:-/tmp}/simd-codegen-oracle-$$"
41+
trap 'rm -rf "$SCRATCH"' EXIT
42+
mkdir -p "$SCRATCH/src"
43+
cp "$HERE/probes.rs" "$SCRATCH/src/main.rs"
44+
cat > "$SCRATCH/Cargo.toml" <<EOF
45+
[package]
46+
name = "simd-codegen-oracle"
47+
version = "0.0.0"
48+
edition = "2021"
49+
50+
[dependencies]
51+
ndarray = { path = "$REPO", default-features = false, features = ["std"] }
52+
53+
[profile.release]
54+
debug = false
55+
EOF
56+
57+
# The measured baseline is DECLARED, never inherited. Two independent reasons,
58+
# and the first alone is NOT sufficient:
4459
#
45-
# `.cargo/config.toml` sets `-Ctarget-cpu=x86-64-v3` via
46-
# `[target.'cfg(target_arch = "x86_64")'].rustflags`, but cargo's RUSTFLAGS
47-
# env var REPLACES that config wholesale — the two do not merge. CI sets
48-
# `RUSTFLAGS: "-D warnings"` at workflow level (.github/workflows/ci.yaml),
49-
# so on CI the target-cpu flag is silently DROPPED and everything compiles
50-
# at baseline x86-64 (SSE2). Verified:
51-
# $ cargo build -v | grep target-cpu -> target-cpu=x86-64-v3
52-
# $ RUSTFLAGS="-D warnings" cargo build -v | grep target-cpu -> (empty)
60+
# 1. cargo resolves .cargo/config.toml from the CURRENT WORKING DIRECTORY,
61+
# not from --manifest-path. Running from elsewhere silently misses the
62+
# repo's config. Hence the `cd "$REPO"` below.
63+
# 2. Even from the right directory, cargo's RUSTFLAGS env var REPLACES
64+
# `[target.'cfg(...)'].rustflags` rather than merging with it. CI sets
65+
# RUSTFLAGS="-D warnings" at workflow level, which drops the target-cpu
66+
# pin entirely:
67+
# $ cargo build -v | grep target-cpu -> x86-64-v3
68+
# $ RUSTFLAGS="-D warnings" cargo build -v | grep ... -> (nothing)
5369
#
54-
# An oracle that inherits the ambient baseline therefore measures a
55-
# DIFFERENT machine's codegen depending on where it runs, which is exactly
56-
# the class of error it exists to catch. Passing `-C target-cpu` after the
57-
# `--` puts it on the final rustc invocation, where it wins regardless of
58-
# RUSTFLAGS.
59-
case "$TARGET" in
60-
x86_64-*) BASELINE_CPU="x86-64-v3" ;;
61-
*) BASELINE_CPU="" ;;
62-
esac
63-
64-
if [ -n "$BASELINE_CPU" ]; then
65-
CPU_FLAG="-C target-cpu=$BASELINE_CPU"
66-
echo "==> baseline: $TARGET @ target-cpu=$BASELINE_CPU (declared, not inherited)"
70+
# Only passing `-C target-cpu` on the final rustc invocation survives both.
71+
# An oracle that inherits its baseline measures a different machine depending
72+
# on where it runs -- exactly the class of error it exists to catch.
73+
if [ -n "$CPU" ]; then
74+
CPU_FLAG="-C target-cpu=$CPU"
75+
echo "==> baseline: $TARGET @ target-cpu=$CPU (declared, not inherited)"
6776
else
6877
CPU_FLAG=""
6978
echo "==> baseline: $TARGET @ target default (no target-cpu override)"
7079
fi
7180

72-
echo "==> building simd-codegen-oracle (--emit asm) for $TARGET"
81+
cd "$REPO"
82+
echo "==> building probes (--emit asm) for $TARGET"
7383
if [ "$TARGET" = "$(rustc -vV | sed -n 's/^host: //p')" ]; then
7484
# shellcheck disable=SC2086
75-
cargo rustc --release --manifest-path "$MANIFEST" -- --emit asm -C debuginfo=0 $CPU_FLAG
85+
cargo rustc --release --manifest-path "$SCRATCH/Cargo.toml" -- \
86+
--emit asm -C debuginfo=0 $CPU_FLAG
7687
else
7788
# shellcheck disable=SC2086
78-
cargo rustc --release --manifest-path "$MANIFEST" --target "$TARGET" -- --emit asm -C debuginfo=0 $CPU_FLAG
89+
cargo rustc --release --manifest-path "$SCRATCH/Cargo.toml" --target "$TARGET" -- \
90+
--emit asm -C debuginfo=0 $CPU_FLAG
7991
fi
8092

81-
# Excluded crate -> cargo places `deps/` either under the crate's own target
82-
# dir or falls back to the workspace target dir, exactly like neon/wasm-parity.
83-
ASM=""
84-
for CAND_ROOT in "$ROOT/crates/simd-codegen-oracle/target" "$ROOT/target"; do
85-
if [ "$TARGET" = "$(rustc -vV | sed -n 's/^host: //p')" ]; then
86-
CAND_DIR="$CAND_ROOT/release/deps"
87-
else
88-
CAND_DIR="$CAND_ROOT/$TARGET/release/deps"
89-
fi
90-
if [ -d "$CAND_DIR" ]; then
91-
FOUND="$(ls -t "$CAND_DIR"/simd_codegen_oracle-*.s 2>/dev/null | head -n1 || true)"
92-
if [ -n "$FOUND" ]; then
93-
ASM="$FOUND"
94-
break
95-
fi
96-
fi
97-
done
98-
93+
ASM="$(find "$SCRATCH/target" -name 'simd_codegen_oracle-*.s' 2>/dev/null | head -1)"
9994
if [ -z "$ASM" ]; then
100-
echo "==> could not locate emitted simd_codegen_oracle-*.s under $ROOT" >&2
101-
exit 91
95+
echo "==> no emitted assembly found under $SCRATCH/target" >&2
96+
exit 92
10297
fi
10398

104-
echo "==> analyzing $ASM against $BASELINE"
105-
python3 "$ROOT/scripts/codegen_oracle_analyze.py" "$ASM" "$BASELINE" "$@"
99+
echo "==> analyzing $(basename "$ASM") against $(basename "$BASELINE")"
100+
python3 "$HERE/analyze.py" "$ASM" "$BASELINE" "$@"

.claude/knowledge/simd-one-spec-design.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ shift-or composition written explicitly.
173173
- Ten currently-unlowered AVX2 int types: free.
174174
- The "is this fast enough?" argument: answered by a twenty-minute
175175
measurement during design, instead of debated.
176+
- ~13k LoC of hand-maintained backend code: substantially reduced, with the
177+
remainder being exactly the intrinsics that earn their place.
176178

177179
## On tooling — why this is NOT a CI job
178180

@@ -191,8 +193,6 @@ the answer goes in a doc. It is not re-answered on every commit.
191193
Run it when a codegen question is genuinely open:
192194

193195
```sh
194-
see .claude/knowledge/simd-codegen-oracle/README.md # host, x86-64-v3 baseline
195-
see .claude/knowledge/simd-codegen-oracle/README.md aarch64-unknown-linux-gnu
196+
sh .claude/knowledge/simd-codegen-oracle/run.sh # host, x86-64-v3 baseline
197+
sh .claude/knowledge/simd-codegen-oracle/run.sh aarch64-unknown-linux-gnu # cross-target
196198
```
197-
- ~13k LoC of hand-maintained backend code: substantially reduced, with the
198-
remainder being exactly the intrinsics that earn their place.

0 commit comments

Comments
 (0)