Say what the objdump actually showed, and where it showed nothing
The first version of both notes claimed a call to fmod in any build with a typed float % in it. A literal pair is folded before any call exists, which is the same fact two paragraphs further down explaining why the corpus block uses globals. Both now say the measurement: the calls are in the build whose operands come through globals.
This commit is contained in:
parent
58d5ccda94
commit
6896128407
29
FIX.org
29
FIX.org
@ -675,9 +675,11 @@ the dev loop's default backend, which is what turned a backend gap into a
|
||||
thing the author hit while writing ordinary code.
|
||||
|
||||
Fixed by calling the same function LLVM calls. There is no SSE remainder
|
||||
instruction and LLVM does not invent one: at -O0 it lowers frem to fmod or
|
||||
fmodf, which objdump shows as a call to the PLT stub in any build of a program
|
||||
with a typed float % in it. x86.ml now loads the two operands into xmm0 and
|
||||
instruction and LLVM does not invent one: a frem that reaches the code
|
||||
generator becomes a call to fmod or fmodf, which objdump shows as a call to
|
||||
the PLT stub — fourteen of them in a build of the probe whose operands come
|
||||
through globals, and none at all in one written with float literals, where the
|
||||
pair is folded to its answer before any call exists. x86.ml now loads the two operands into xmm0 and
|
||||
xmm1 — already the SysV argument registers — and calls fmod or fmodf by width.
|
||||
Agreement is then by construction rather than by a second hand-written
|
||||
identity that would have to get every rounding, every signed zero and every
|
||||
@ -702,13 +704,14 @@ build. So a corpus program that exercises a construct is already a test that
|
||||
the two backends agree about it, and the float % cases added to math3.flan are
|
||||
in that set by being in test/programs.
|
||||
|
||||
What @x86 does not do is fix the LLVM side at -O0. It builds both sides with
|
||||
whatever the default optimisation is, so a construct LLVM folds at compile
|
||||
time — a % over two float literals is one; the operator never survives to the
|
||||
IR — is compared as a constant against the x86 backend's actual lowering. The
|
||||
float % block in math3.flan goes through globals for that reason, the same
|
||||
reason arith.flan gives for its own. Two things would close the rest of the
|
||||
gap: a SURVEY_FLAGS=-O0 pass, so the LLVM side emits the calls and branches
|
||||
rather than the answers, and something that walks the two prim match arms
|
||||
mechanically rather than relying on somebody reading them side by side, which
|
||||
is how this gap survived. Neither is queued.
|
||||
What @x86 does not do is pin the LLVM side at -O0. It builds both sides at the
|
||||
default -O2, so a construct LLVM folds at compile time — a % over two float
|
||||
literals is one: that build contains no fmod call — is compared as a constant
|
||||
against the x86 backend's actual lowering. The float % block in math3.flan
|
||||
goes through globals for that reason, the same reason arith.flan gives for its
|
||||
own. Two things would close the rest of the gap: an -O0 pass of the sweep, so
|
||||
the LLVM side emits the calls and branches rather than the answers — the
|
||||
script already has SURVEY_FLAGS, which hands the same extra flags to both
|
||||
sides, and both sides do accept -O0 — and something that walks the two prim
|
||||
match arms mechanically rather than relying on somebody reading them side by
|
||||
side, which is how this gap survived. Neither is queued.
|
||||
|
||||
13
lib/x86.ml
13
lib/x86.ml
@ -2762,10 +2762,15 @@ and prim f (e : Tast.expr) (p : Tast.prim) (args : Tast.expr list) dst =
|
||||
fload f.b ~dst:1 ~mm:(lmem f lb ~scratch:r11) ~f64;
|
||||
(match p with
|
||||
(* There is no SSE remainder instruction, and LLVM does not pretend
|
||||
otherwise: at -O0 it lowers [frem] to a call to C's [fmod] or
|
||||
[fmodf], which `objdump -d` on any build of a program containing a
|
||||
typed float [%] shows as a [call fmod@plt]. Calling the same
|
||||
function is what makes the two backends agree by construction
|
||||
otherwise: it lowers a [frem] that reaches the code generator to a
|
||||
call to C's [fmod] or [fmodf], which is what `objdump -d` shows as a
|
||||
[call fmod@plt] in a build whose operands come through globals. A
|
||||
[%] over two float literals is folded on the way and contains no
|
||||
call at all, which is why the corpus block that covers this uses
|
||||
globals — a folded answer is evidence about the folder.
|
||||
|
||||
Calling the same function is what makes the two backends agree by
|
||||
construction
|
||||
rather than by a hand-written identity that would have to get every
|
||||
rounding, every sign of zero and every infinity right on its own.
|
||||
The prelude already declares both symbols ([fmod-f32],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user