Repository navigation
[AUTOMATED] Preserve NaN quieting through floating conversions - #1250
Conversation
The quieting fold-guard changed default output on ordinary code: every
i386 x87 float copy (`*d = *s`, compiled as fldl/fstpl) printed as
`(double)((volatile long double){ (long double)*s })`, and every widening
or narrowing of an unknown float gained a volatile compound literal
(178 changed functions across libm/vorbis/mpg123/opus/lame/coreutils).
Signaling-NaN preservation is not promised by C, so this is a policy:
keep it under `nanignore none` (the native-exact NaN mode), and let the
shipped `compare` default drop it as before.
Under `none`, only a widening that feeds a conversion back to its source
format gets the volatile literal; other conversions cannot be erased by
a C compiler and keep ordinary casts. Reverts the datatest, stage and
integration expectations the original change rewrote.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
Resolves the kuna-cli tests/integration.rs module-list conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
Resolves the docs/spec/09-emission.md paragraph conflict (both kept). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
|
[AUTOMATED] Pushed 34a4a43 plus two merges of origin/main (integration.rs and 09-emission.md conflicts). Repro of the problem it addresses (i386, void copyd(double *d, const double *s) { *d = *s; }On the previous head, C does not promise to preserve signaling NaNs, so the quieting now applies only under Default output is byte-identical to the base on that corpus. The 14 remaining diffs also differ between two base runs. Under |
Under `nanignore none`, a widening shared by several readers prints as an
assignment, `v = ((volatile double){ (double)x });`. GCC 11 and 15 at -O2
drop a bare volatile compound literal in that position and fold
`(float)v` back to `x`, so the regenerated code no longer quiets a
signaling NaN the native round trip quiets. Reading the literal as
`(*&(volatile double){ (double)x })` is a volatile access GCC and Clang
keep in every position. The NaN test gains a round trip whose widening
merges through a stack slot, which prints the assignment form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
|
[AUTOMATED] Pushed cdcc8d4 (+ merge of origin/main, 357711a). Under |
…elo-Lab#1241) A pointer copied, offset (PTRADD) or member-addressed (PTRSUB) into an integer variable or member printed as `frame[0] = value;`, which gcc 15 and clang reject. Emit an explicit cast to the destination's printed integer type. Skip it when the source variable is itself declared as a same-width integer, and print a copied null pointer as `0`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
…Lab#1249) Storage-cast reconciliation now runs in both directions: a same-width integer value assigned to a declared pointer member or variable gets a pointer cast. A CAST statement is judged by the type its result prints, so a pointer-typed CAST assigned to integer storage gets the integer cast (`len = (long)(char *)&len[1];`). A member type comes from the whole Symbol only when that Symbol is a struct, array or union; a scalar local or global keeps the type its declaration prints. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
The implied-word-cast test ran under `nanignore none` only because the x87 `flds; fstps` pair after the word copy used to fold to a word COPY under every policy. Under `none` that pair now keeps its sNaN quieting, so it is a float reader of the copied word. The copy then prints as a float member copy, which is how the default policy already prints a word copy that feeds float arithmetic. The default policy still folds the pair, which is the shape the test pins, so it now runs there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
|
[AUTOMATED] Pushed d46b50b. Merged with main, |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEr111CDLJsQMzY3YSyWXD
An x87 load/store or SSE conversion round trip quiets a signaling NaN. Kuna previously reduced it to a COPY: input
0x7f800001returned unchanged instead of native0x7fc00001.Reproduce on an unmodified engine by adding only the independent test:
RuleFloatCastandSubfloatFlownow retain the conversion when its input might still be signaling. A bounded provenance walk permits existing folds after quieting operations or for non-NaN constants.nanignore allrestores the previous behavior.Keeping the IR conversion is insufficient: GCC also erased the old C cast pair with strict rounding flags. C emission therefore materializes a potentially quieting conversion in a volatile compound literal, evaluating its operand once. Already quiet inputs retain ordinary casts.
Validation: fresh x87 float32/float64 and SSE float32 fixtures, 4,108 patterns per format, four rounding modes, Clang/GCC at O0/O2, both
nanignore noneandcompare; before failure and after pass. Also passed 39 rule tests, 17 cast-rendering tests, existing integer/intermediate rounding and native i386 return controls, andmake check-spec. Full suite left to CI.The nine affected corpus rendering assertions now require the retained volatile conversions. All 48 assertions in those four files pass locally; assertion names/counts and the recorded baseline are unchanged.
Also passed the 19 assertions in the four affected stage files. Their finite-only simplification controls now state
nanignore allexplicitly; strict NaN policies remain covered by native comparisons. No baseline counts were changed.Updated nine integration rendering checks to require the volatile conversion expressions. All 56 tests across the six affected integration modules passed locally, including their generated-C recompilation checks. The first local pass lacked non-x86 specs for one module; rerunning that module with the installed complete spec tree passed all 16 tests.