Whitepaper: Fast-math DCE in pure-Li benchmark verification (2026-05-22)¶
Summary¶
While adding result verification for tier-1 micro-benchmarks, we found that a pure-Li simd_dot implementation could pass a naive “program runs and prints a number” check while doing essentially no work. The printed checksum was 0, wall time was ~1 ms for a nominal 10⁷-element dot product, and LLVM had eliminated the computation under -O3 -ffast-math, not because we intended an optimized empty kernel.
This document is for internal review and external reporting: what happened, why our old checks were insufficient, and what we changed.
Intended benchmark¶
Name: simd_dot (tier-1 micro).
Normative semantics (benchmarks/tier1_micro/common/dot_core.c):
N = 10_000_000- For each
i:a[i] = (i & 255) * 0.001,b[i] = ((i * 7) & 255) * 0.002(float64) acc = Σ_i a[i] * b[i]- Expose
accas the checksum (expected magnitude ~3.4×10⁵, not zero)
Performance intent: measure throughput of Li’s array @ array / dot lowering at large N, comparable in work to the shared C kernel used by cpp/rust/julia labels.
What we built first (pure-Li)¶
Early pure-Li drivers used smaller tiles (e.g. 800×array[40000]) or different init/reduction than dot_core.c. Result verify against native correctly failed (Li ≈ 64 vs native ≈ 340367) — good.
We then aligned init and total N with the C spec (tiled 10M, LUT / loop-based float init). Numerical parity with native was still wrong in another way:
| Build | Wall time (order of) | Checksum |
|---|---|---|
Native (-O3 -ffast-math, shared dot_core.c) | ~0.05–0.1 s | 340367.6243199876 |
Pure-Li (-O3 -ffast-math, tiled loops + li_rt_volatile_sink_f64) | ~0.001 s | 0 |
So Li vs native verify would have failed on checksum — but the important signal is time + magnitude: the Li binary was three orders of magnitude too fast and summed to zero.
Root cause (compiler / flags, not “wrong formula”)¶
With --release -O3 -ffast-math -march=native (harness default for tier-1 Li):
- LLVM treated the hot loop as dead or foldable to zero (unsafe math assumptions + no observable side effect on the reduction until the final sink).
li_rt_volatile_sink_f64(acc)on the finalaccalone was not enough to keep the whole 10M-term reduction alive when intermediate array fills and partial sums were provably unused or folded.- This was unverified elimination — not forbidden DCE. Allowed DCE must still pass our spec, goldens, and timing guards (see policy below).
Isolated tests (e.g. dot_lut_a(42) returning 0.042) still worked; the full main + fast-math path did not.
Mitigation in tree today: simd_dot Li links LI_EXTRA_C / dot_core.c (same kernel as native) until pure-Li codegen keeps observable work. Matmul pure-Li paths did not show the same total fold (large stack matrices retain memory effects).
Why “compare to C++” was not enough¶
Our first verify pass was Li checksum vs native --verify. That catches divergence but not all failure modes:
| Failure mode | Li vs native only | Normative spec + guards |
|---|---|---|
| Li wrong, native right | Fail | Fail |
| Both wrong the same way | Pass | Fail (vs spec / small golden) |
| Li DCE → 0, native correct | Fail | Fail (magnitude + time) |
| Li DCE → 0, native also broken | Pass | Fail |
Python (or any other runtime) is useful as a second implementation of the spec in reference.py, not as the definition of truth. Goal remains: correct per spec, as fast as possible; matching others is a sanity check.
What we added (verification we own)¶
benchmarks/harness/reference.py— float64 reference loops mirroring*_core.c; small-N exact and large-N with tolerance.verify_benchmark_results— native and Li must match spec;|result|floors; min Li wall time on pure-Li rows; optionalBENCH_VERIFY_TIMING.scripts/verify-math-physics-goldens.sh— library-scale small goldens (math@/sum, physics mini checksums).- Cursor rule
li-benchmark-correctness.mdc— correct-first policy; DCE allowed, verification required.
Recommendations (product / compiler)¶
- Pure-Li tier-1 dots: require observable reduction in codegen (e.g. volatile store per tile,
noinlinekernel boundary, or-ffast-mathoff for verify builds) until a single sink at the end is proven sufficient. - CI: keep
./scripts/bench-verify-results.sh 1and math/physics golden script on release paths. - Reporting: do not publish “pure_Li simd_dot” throughput until verify shows non-zero spec checksum at realistic wall time.
References in repo¶
- Harness:
benchmarks/harness/bench.py,benchmarks/harness/reference.py - Incident driver history:
benchmarks/tier1_micro/simd_dot/li/main.li(comment: shared kernel until pure-Li anti-DCE) - Policy:
.cursor/rules/li-benchmark-correctness.mdc,benchmarks/results/README.md