The x86 survey compares against LLVM built at -O0, the level the hand-written backend corresponds to

This commit is contained in:
Joseph Ferano 2026-09-25 15:15:25 +07:00
parent b0323606fc
commit 52c154e306
3 changed files with 14 additions and 17 deletions

View File

@ -1085,13 +1085,6 @@ Every program in the corpus that compiles, has a =main= and terminates agrees wi
the LLVM build down to stderr. =docs/BUILT.md=, "The hand-written x86 backend, and the LLVM build down to stderr. =docs/BUILT.md=, "The hand-written x86 backend, and
the four measurements behind it", is the account. the four measurements behind it", is the account.
** NEXT Nothing pins the LLVM side at -O0 when the two backends are compared
Decided 2026-09-25: the x86 parity survey compares against LLVM at -O0 only; -O2 is never its target. The acceptance suite's paired -O2/-O0 rows stay, being the check for undefined behaviour in emitted IR, which is a different question.
The survey builds both sides at the default =-O2=, so a construct LLVM folds is
compared as a constant rather than as a lowering. That is how the float =%= gap
survived. Two things would close it: an =-O0= pass of the sweep, and something
that walks the two backends' primitive match arms mechanically. Neither is queued.
** DONE Reading (uninit) before writing it is undefined behaviour ** DONE Reading (uninit) before writing it is undefined behaviour
CLOSED: [2026-09-25] CLOSED: [2026-09-25]
Reading an =(uninit)= value before writing it is undefined behaviour, and the backends may differ on it. An exhausted match stays =ud2= on x86. Reading an =(uninit)= value before writing it is undefined behaviour, and the backends may differ on it. An exhausted match stays =ud2= on x86.

View File

@ -161,7 +161,8 @@
; second backend still lowers the language: it refuses by name rather than ; second backend still lowers the language: it refuses by name rather than
; miscompiling, so when another lane adds a primitive the backend says so ; miscompiling, so when another lane adds a primitive the backend says so
; loudly, and nothing was listening. Two such refusals sat in the tree for a ; loudly, and nothing was listening. Two such refusals sat in the tree for a
; month. Now they fail a build somebody can run. ; month. Now they fail a build somebody can run. The LLVM side is built at
; -O0, the level this backend corresponds to.
; ;
; dune build --root . @x86 ; dune build --root . @x86
; ;

View File

@ -20,6 +20,11 @@
# compared a checked build against an unchecked one would say nothing about # compared a checked build against an unchecked one would say nothing about
# bounds.flan, which is the one program the two backends disagreed about. # bounds.flan, which is the one program the two backends disagreed about.
# #
# The LLVM side is built at -O0, never at the default -O2. This backend has no
# optimiser, so -O0 is its counterpart: at -O2 LLVM folds a constant
# expression before it is lowered, and the sweep then compares a lowering
# against a constant. That is how the float % gap stayed hidden.
#
# Six outcomes, and the third is the progress meter: # Six outcomes, and the third is the progress meter:
# #
# MATCH built both ways, same stdout, same stderr, same exit status # MATCH built both ways, same stdout, same stderr, same exit status
@ -91,14 +96,12 @@ forever="dev-loop dev-watch dev-chatty agent-auto"
# in the epilogue that every exit already went through. The five are in the # in the epilogue that every exit already went through. The five are in the
# sweep now and they are five of the MATCHes. # sweep now and they are five of the MATCHes.
# The one whose whole point is a fault, and which therefore cannot be compared # The one whose whole point is a fault. dev-segv stores through a null
# at this sweep's optimisation level. dev-segv stores through a null pointer, # pointer, which is undefined, so neither side's answer is a lowering to
# which is undefined: what LLVM at -O2 does with it is its own business, and # compare. test_dev.ml builds it in a dev session, where the fault is the thing
# this backend has no optimiser and exits 139. That is not a lowering # asserted. It also calls agent/start, so it leaves a socket in /tmp on both
# disagreement. test_dev.ml builds it in a dev session, # runs, and under SURVEY_FLAGS=--dev it parks in the break loop instead of
# where the fault is the thing asserted. It also calls agent/start, so it # dying.
# leaves a socket in /tmp on both runs, and under SURVEY_FLAGS=--dev it parks
# in the break loop instead of dying.
faults="dev-segv" faults="dev-segv"
TIMEOUT=${TIMEOUT:-20} TIMEOUT=${TIMEOUT:-20}
@ -126,7 +129,7 @@ for src in "$corpus"/test/programs/*.flan; do
# LLVM first. A program that does not compile at all, or has no main, is not # LLVM first. A program that does not compile at all, or has no main, is not
# this backend's business -- the frontend refused it either way. # this backend's business -- the frontend refused it either way.
if ! "$flan" build "$src" "${extra[@]}" -o "$out/$name.llvm" \ if ! "$flan" build "$src" -O0 "${extra[@]}" -o "$out/$name.llvm" \
>"$out/$name.llvm.err" 2>&1; then >"$out/$name.llvm.err" 2>&1; then
# A package the build tree does not have is not the frontend refusing # A package the build tree does not have is not the frontend refusing
# the program: it is a sweep that did not look at it, and it is counted # the program: it is a sweep that did not look at it, and it is counted