Archive — history, not state. Kept for its reasoning and its evidence; its plan is closed.

Mach exact type-span consumption and constant-load fusion audit

Date: 2026-07-13 Base: f797cc91 Experiment branch: codex/perf-mach-exact-fusion

This experiment had two independent questions:

  1. Can Mach replace the _has_inline_splice whole-function fact ban with the exact final-index _type_spans already produced for native lowering?
  2. Does an adjacent numeric LOADI/LOADK plus arithmetic/comparison superinstruction occur often enough to justify more VM text?

The first arm is accepted on this branch. The second was implemented, measured, rejected, and deleted. Neither arm adds a semantic mcode operation or changes runtime object/frame layout.

A. Exact facts on inline-spliced hosts: accepted

Old behavior

One inline splice set _has_inline_splice on the host. Mach lowering then discarded the host’s entire _write_types and _no_overflow tables. That was a necessary emergency guard after composed fannkuch exposed a false add_iip claim, but it also disabled valid typed arithmetic everywhere else in the host.

New selection rule

Mach now extracts only the int entries from _type_spans and asks for both operand types at the current final semantic-mcode instruction index. The rule is deliberately asymmetric:

  • inline-spliced host: both operands must have exact covering int spans; function-global _write_types is never a fallback;
  • non-spliced host: exact spans are preferred, then the existing conservative function-global fact may be used;
  • _no_overflow is still consumed only at its exact final instruction index.

The extracted C table is compiler-transient. It has three int fields (12 bytes) per source type span during Mach lowering and is freed before lowering returns. No new actor heap, frame slot, object header, or executable-code sidecar is retained.

The existing serialized instr_facts byte table is now freed immediately after load-time opcode selection. The selected opcode byte contains the entire runtime decision; retaining one fact byte per instruction in shared code was dead state. The original serialized bytes remain in the code-cache key, so cache identity remains exact.

Historical failure, now made exact

Fannkuch’s former failure was at final mcode indices 576/577. The optimized stream now records one operand as int and the overflow-promoted carrier as num. Exact Mach lowering therefore leaves both operations generic. Under the debug/ASAN build, with PIT_MACH_DEBUG_CONTRACTS active, full fannkuch returns the exact 3000008629 result without a fact assertion.

aot_bench/regress/mach_inline_fact_spans.ce is a compact automated version: it forces a known function to inline, obtains arguments through an array, and checks the 30 * 100000000 + 8629 promotion chain in both Mach and native. tests/compile.cm additionally verifies that the post-multiply add does not have two exact int operand spans before executing its Mach blob.

Controlled performance

The experiment branch temporarily used PIT_MACH_NO_EXACT_SPAN_FACTS=1 to disable only exact facts on spliced hosts. That made the controlled pair leave the runtime binary, all other fusion, source, compiler output, and native lane unchanged. The switch and disabled path were deleted before integration; the accepted implementation always uses the exact facts when they exist.

call_hot is a known-inlined numeric host and is the real coverage row:

statedynamic handlersdispatchesserialized Machmedian
old splice banadd 4,000,000; mul 2,000,000; fuse_lt_br 2,000,00118,000,0253,944 B14.410 ms
exact spansadd_ii 4,000,000; mul_ii 2,000,000; fuse_lt_br_ii 2,000,00118,000,0254,144 B13.313 ms

That focused 11-sample pair is 7.6% faster. Three independent process medians (each itself seven samples) were 13.22 ms exact versus 13.94 ms disabled, a more conservative 5.2% win.

The +200-byte artifact delta is the optional facts section for this small inlined unit (5.1%). It is shared per cached program, not per actor, and is not retained a second time in PitCodeRegister. The compiler’s already-existing 23 _type_spans occupy 1,056 live host bytes for this unit; this arm does not create or enlarge that producer table.

The important negative coverage is also exact:

rowexact typed-handler changedispatch changeMach bytesresult
fannkuchnone030,760 B, unchanged3000008629
spectralnormnone088,760 B, unchanged1623647009

Those programs’ hot arithmetic is genuinely num, not int. Exact spans avoid the old miscompile but do not manufacture optimization coverage.

Runtime code-size tradeoff

Release binaries were built from clean worktrees with the same toolchain:

metricf797cc91accepted armdelta
dylib file1,454,232 B1,454,264 B+32 B
__text1,029,324 B1,030,440 B+1,116 B
__cstring56,461 B56,502 B+41 B

The target cost is about 1.2 KiB shared runtime text plus facts bytes only in artifacts whose spliced code actually receives typed handlers. A 5-8% win on inlined integer loops is worth that bounded cost even for small-console profiles; unlike a cache or shape table, it has no per-actor multiplier. A future ultra-small distribution can still compile the feature out as a profile choice if 1 KiB is more valuable than the speed.

B. Adjacent numeric load/use fusion: rejected and deleted

The prototype added only two target-private heads:

  • fused LOADI plus generic numeric use;
  • fused numeric LOADK plus generic numeric use.

The second word stayed unchanged and independently targetable, and the handler always wrote the load’s carrier slot before performing the use. Eligible uses were add/subtract/multiply/divide and the six comparisons. The loader refused to replace a fact-typed integer operation or a comparison already eligible for compare/branch fusion, because either existing specialization removes at least as much work.

It passed the selected cross-lane matrix, but normal optimization removes the adjacency that the opcode needs: LICM hoists constants, while dynamic numeric guards sit between the remaining loads and their uses.

  • float_math: zero dynamic fused uses.
  • arith_int and call_hot: zero; their uses already had stronger typed handlers.
  • fannkuch: exactly one dispatch removed out of 232,394,869; paired seven-run medians were 290.63 ms disabled and 292.58 ms enabled (noise/regression).
  • spectralnorm: exactly one dispatch removed out of 224,432,185.
  • serialized Mach was byte-identical under the load-time toggle; no per-code state was added.

The prototype changed the dylib file by +176 bytes, while compiler/linker layout and tail-merging made raw __text move by -5,504 bytes; neither size signal matters beside the decisive absence of dynamic coverage. The two opcodes, handler, toggle, and tests were deleted. A future constant-operand experiment should consume non-adjacent _const_spans at the arithmetic use and remove actual loads/carrier stores; adjacency fusion is the wrong lever for the current optimized stream.

Tooling correction

aot_bench/census.ce now implements the same typed one-shot run command as the focused benchmark tool. Previously the legacy bare-script help probe could kill it before it printed a long composed census. The actor now replies with the exact result, dispatch total, serialized Mach bytes, and median while retaining its per-opcode console census. This change is committed separately from the performance arm.

Validation receipts

  • release fannkuch: exact 3000008629;
  • debug+ASAN fannkuch with Mach fact contracts: exact 3000008629, no contract violation;
  • selected native/Mach matrix: regression, call_hot, fannkuch, spectralnorm all match;
  • targeted compiler suite after regression addition: 73/73;
  • first cold default-suite attempt: 832/833, with only vm_suite timing out while its realization was still charged to the deadline;
  • isolated warm vm_suite: 1,086/1,086;
  • warm default suite: 1,918/1,918;
  • seeded fuzz, ./pit fuzz 500 --seed 20260713: 3,733/3,733.

The cold timeout is the existing daemon/realization deadline problem, not a wrong-result or crash: the same suite passed immediately after realization, and its isolated language/VM payload was fully green.

Source: plans/archive/perf-2026-07/perf-campaign-mach-exact-spans.md