passes_to_x86, and the five-second probe that called it2026-09-04. Third in a series about retiring the ladder: what is worth taking.
ir_to_x86_on_cce turned out to be a capacity test that had caught one thing,
on purpose, and we dropped it. passes_to_x86 is a different animal, and the
difference is worth being precise about, because one of its two rungs is the
most load-bearing thing in the ladder and the other has already done its job.
ir_to_x86The same back end, with the IR pipeline switched on. emit_harness.py carries a
passes flag: ir_to_x86's two rungs run with it off, passes_to_x86's two run
with it on, and what it inserts is the middle end — Simplify, Occurrence,
LambdaLifting, Passes, IRCheck — exactly where compile-frontend-passes
calls run-ir-pipeline.
That is also what decides the unit's contents, in a way worth writing down: IR emission prunes to what the opening reaches, so that one call is the only reason the pass chapters end up in the IR at all. Remove it and they vanish from the subject, silently.
passes_to_x86_on_mid load-bearingFrom its own docstring, and it is the best sentence in the ladder:
The subject is chosen to make the middle end DO something. Transpiling the pass chapters and running them are two different claims, and fib only tested the first: with fib the pipeline is a no-op —
doubleis dead,fibis recursive so nothing inlines, nothing folds — sowhole.truthcame out byte-identical toir_to_x86_on_fib.truthand the passes could have been broken without the oracle noticing.
That is the exact failure mode this whole retirement exercise is about: a green check that is green because it never ran. A rung compiled the entire middle end, emitted a binary, compared it byte for byte against bare metal — and would have passed with the middle end removed, because the subject gave it nothing to do.
The fix was the subject, not the harness. Chapter: Mid is built so each of
default-ir-pipeline's three passes has something to bite on:
| pass | what bites |
|---|---|
fold-constants |
a 7 * 6 in the driver |
inline-leaf-calls |
double is a leaf and is actually called |
inline-single-caller |
scale-by-four has exactly one call site |
fib stays for the recursion, which nothing inlines, so a real call survives in
the emitted code. Everything is integer arithmetic with one printed answer: the
work under test is the compiler, not the program it compiles.
That is a designed experiment, and nothing else in the toolchain asks its question. The transpilers demand a fixed point on the zig path. The corpus checks answers, not the emitted image. Nothing but this compiles the whole compiler with its middle end live and compares the machine code against bare metal's, byte for byte.
Its own docstring names the comparison it beats: "The C# arm pushes the whole compiler through its plug and stops at 'the emitted C# compiles'; this pushes the whole compiler through the zig plug and compares the binary it emits, byte for byte, against bare metal's."
passes_to_x86_on_arith was built to answer one question, and it answeredThe second rung is a different kind of thing: not a standing check but an
instrument built to attribute a specific failure. The hosted compiler compiled
codex/test/plug-oracle-arith.codex into a binary that agreed for seventeen
values and then faulted with !EXC=06 — an invalid opcode — where the
seed-compiled binary printed 100 / -100 / 42. Those three come from a record
field typed Integer between -100 and 100 clamping.
Two hypotheses, and the rung was designed to separate them:
(a) the zig plug mis-transpiled the clamping path of the x86 emitter, so the transpiled compiler emits different x86 than bare metal does; (b) the transpilation is faithful and the harness is at fault … or current source differs from the frozen seed here.
If the arms agree, the transpilation is faithful and (b) holds; if they differ, (a) does, and the diff names the instruction.
Today the arms agree. passes_to_x86_on_arith is green on u56-candidate, and
has been since Update 53. The experiment ran and returned (b).
That is a rung that succeeded, and succeeding is not the same as being needed forever. What it is now is a regression guard on a question already settled — useful, but a much weaker claim than the one that justified building it, and one of the two subjects riding in a unit whose compile is 2.58 MB.
The sharpest thing in this corner of the record has nothing to do with either
rung. plug-oracle-arith.codex has a second job: it is the seed canary.
At Update 53 it was compiled by both seeds on bare metal — one subject,
unchanged between the releases, so the seed is the only variable — in five
seconds a side. From U53.log:
bank_diff u51 -> u53: three moved, eleven held.ir_to_x86_on_fib,ir_to_x86_on_cce,passes_to_x86_on_mid— but NOTlir_to_x86orpasses_to_x86_on_arith, so a subset of the x86 family and not the whole of it. The canary called this shape from a five-second probe.
A ten-second experiment predicted which of fourteen rungs would move, in a sweep
that costs hours. It also caught something the sweep could not: seed_identity.py
did not recognise the new release's note, "the second release form it has needed
teaching, and the canary is where it should be caught."
I do not think that has been given its due. The canary is not a smaller version of the ladder; it is a different and better instrument for the question "did anything move", and the rungs' job is the narrower one of saying what moved once you already know something did.
Carry the middle-end claim. One subject, designed so the pipeline has something to bite on, compiled whole and compared against bare metal. It is the only check anywhere that the middle end runs rather than merely transpiles, and the docstring's own history proves the naive version of it was vacuous.
Do not carry the arith rung. It answered its question in Update 53 and returned (b). If the clamping fault comes back, the instrument is thirty lines and a subject that already exists; rebuilding it then is cheaper than running it until then.
Carry the canary instead, and give it a name. Compile one unchanged subject
under two seeds and diff. Five seconds. It called the shape of a multi-hour
sweep and found a tooling gap the sweep could not. In codex-qemu that is a
verify_-shaped script, not a rung: did anything move between these two
trees? — asked before anyone spends six minutes, let alone an afternoon.
And notice what the three essays have converged on. Each of the ladder's
expensive things reduced to a cheap question it was answering indirectly:
ir_to_x86_on_cce to "who compiles something large to x86"; f3_run and
f4_boot to "do emitted x86 bytes work"; passes_to_x86_on_arith to a
hypothesis that has been settled for three Updates. Only passes_to_x86_on_mid
survives contact, and it survives because somebody noticed its first version was
vacuous and fixed the subject.
That is the pattern worth carrying, more than any of the code: the checks that earned their keep are the ones where somebody asked what the check would look like if it were passing for the wrong reason.