The handoff carries the headline and what was left undone

This commit is contained in:
Joseph Ferano 2026-09-13 23:27:29 +07:00
parent 69129fc29f
commit 219a42ed5b

View File

@ -41,10 +41,24 @@ touches no `(modules ...)` list, so it cannot be pulled into `@runtest` by accid
`clang: error: linker command failed` lines it prints are the `dev-robust` fixture doing its job and are called `clang: error: linker command failed` lines it prints are the `dev-robust` fixture doing its job and are called
out in `HANDOFF-x86-rt.md` §4 already. out in `HANDOFF-x86-rt.md` §4 already.
## 2. The measurement — `spike/x86/cost.sh`, `spike/x86/bench.sh`, `spike/x86/COST.md` ## 2. The measurement — `spike/x86/COST.md`
`COST.md` is the deliverable and it carries the numbers and the reading of them. The two scripts are how it was `COST.md` is the deliverable and it carries the numbers and the reading of them; the raw rows are committed beside
produced: it as `cost-corpus.tsv` and `cost-bench.tsv`. The headline, in one paragraph:
**This backend emits 3.84× the code LLVM does at `-O2`, and 1.92× what LLVM emits at `-O0`** — half the factor is
the optimiser Flan ships with and not the backend. Per program the second ratio is tight: median 2.21, quartiles
1.94 and 2.98. Speed is unmeasurable over the corpus (every program is 2.5ms of `execve`) except `recur`, which
loops ten million times and is **6× LLVM `-O0`**; on purpose-written loops the backend is 2.8× to 4.7×.
Of the five suspected costs the old handoff named, the measurement says: the frame-slot round trip on every
intermediate is most of everything and is the item worth fixing; `rep movsb` costs twenty cycles a copy and is
worth fixing cheaply; the bounds check's three temporaries cost 241 bytes and *one cycle*, so they are a code-size
item and not a speed item; the guard after every call is four instructions and invisible; and the dev build's
extra load per call site is not measurable at all. What a dev build does cost — 400× the code, because nothing may
be dropped when anything might be redefined — is `Reach`'s doing and both backends pay it.
The two scripts are how that was produced:
- `cost.sh` sweeps the corpus and prints a TSV: file size, `.text`, and **the sum of the `flan.*` defined symbols**, - `cost.sh` sweeps the corpus and prints a TSV: file size, `.text`, and **the sum of the `flan.*` defined symbols**,
which is the program's own code with the runtime excluded. `COST_FLAGS=--dev` is the `SURVEY_FLAGS` precedent. which is the program's own code with the runtime excluded. `COST_FLAGS=--dev` is the `SURVEY_FLAGS` precedent.
@ -71,3 +85,18 @@ The sweep behind `COST.md` was re-run clean afterwards. If you extend these scri
No finding here wants a compiler change that this lane was not allowed to make. The costs are all in No finding here wants a compiler change that this lane was not allowed to make. The costs are all in
`lib/x86.ml`'s lowering and the next lane rewriting that file will meet them; `COST.md`'s last section says which `lib/x86.ml`'s lowering and the next lane rewriting that file will meet them; `COST.md`'s last section says which
ones are worth its attention and which are not, which was the point of measuring rather than guessing. ones are worth its attention and which are not, which was the point of measuring rather than guessing.
## 5. What was not done
- **The `--dev` sweep over the whole corpus was not finished.** It was started, ran into the `dev-*` programs
(each of which waits out a twenty-second timeout twice), and was killed to free the machine for the clean
release re-run. The `--dev` numbers in `COST.md` come from `bench.sh`, which measures the same thing on four
programs and measures it better, because a corpus program's dev cost is invisible under `execve`. Re-running it
is `COST_FLAGS=--dev spike/x86/cost.sh` and about half an hour.
- **No corpus program was disassembled.** The attribution in `COST.md` is all from the four benchmarks, which are
small enough to read whole and were written so that each one is mostly a single suspected cost. The corpus
outliers are explained from the `-O0` column instead — which is what that column is for, and in `bounds`' case
it turns an alarming 11× into an ordinary 2.07×.
- **`LLVM -O0` is only reachable through `--debug`**, which also asks for DWARF. Checked and harmless: DWARF lands
in `.debug_*` and the metric sums `.text` symbols. A plain `-O0` flag on the CLI would be a `bin/main.ml` change
and this lane was not touching compiler sources.