Repository navigation
Rotation fixes: ?rotmg negative-D1 hang, ?rotg/?rotmg NaN canonicalization, -O1 test bug - #36
Merged
Merged
Conversation
test_cdotu_rounding_modes built the four operand vectors from compound literals inside its loop body. An in-loop compound literal's lifetime ends with the iteration, and clang at -O1 sank the initializing stores for the second cvec argument past the loop's back-edge, so the first iteration multiplied by stack garbage and the assertion failed with a different value on every run. The Makefile builds tests without -O, so this was latent here; it surfaced compiling the suite at -O1 against the Rust port. Hoisted the four literals out as static arrays, as the rest of the file does. The suite now passes at -O0, -O1 and -O2. Fixes #35 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g NaNs Two fixes to the rotation routines, both found by the RustFloat differential fuzzer. They share the four ?rotmg files, so they share a commit. ?rotmg hang (#33). The first rescale loop's guard, `d1 != 0 && d1 <= rgamsq`, never goes false for a negative d1: multiplying by gamsq keeps it negative and pins it at -inf, which is still <= rgamsq. A negative d1 is reachable from valid-looking inputs -- a negative d2 whose q2 = (d2*y1)*y1 underflows to -0 slips past the `q2 < 0` singularity test, and the flag = 1 branch then swaps it into d1. The guard is now `0 < d1`, matching the Rust port, so the loop terminates however d1 became negative. All four precisions. ?rotg / ?rotmg NaN canonicalization (#34). These were the only routines writing their outputs without nan_unify_*, so a NaN came back carrying SoftFloat's propagated payload and sign instead of SINGNAN / DOUBNAN / HALFNAN / QUADNAN -- the property the rest of the library guarantees for the Hoon path. The stores are now unified, ?rotm-style. ?rotmg unifies only the values it actually writes: the p2 == 0 early return still leaves D1/D2/X1 untouched, and only the P[1..4] entries that the flag selects are written. ?rotg unifies c and s before a and b, preserving the previous store order for an aliasing caller. 12 regression tests (4 + 8, all precisions). Each fails against the pre-fix sources -- the four ?rotmg termination tests hang there. Note that a sign-only NaN is not a discriminating input under the 8086 specialization this repo builds, since f_abs clears the sign before the NaN reaches the arithmetic, so the ?rotg tests use signaling NaNs; the sign leak in the issue was observed against an ARM-VFPv2 build. Fixes #33 Fixes #34 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the three open issues, all found by the RustFloat differential fuzzer.
#33 —
?rotmgloops forever whend1goes negativeThe first rescale loop's guard,
d1 != 0 && d1 <= rgamsq, never goes false for a negatived1: multiplying bygamsqkeeps it negative and pins it at-inf, which is still<= rgamsq. A negatived1is reachable from valid-looking inputs — a negatived2whoseq2 = (d2*y1)*y1underflows to-0slips past theq2 < 0singularity test, and theflag = 1branch then swaps it intod1.The guard is now
0 < d1, matching the Rust port, so the loop terminates howeverd1became negative. All four precisions.#34 —
?rotgand?rotmgdo notnan_unifytheir outputsThese were the only routines writing outputs without
nan_unify_*, so a NaN came back carrying SoftFloat's propagated payload and sign instead ofSINGNAN/DOUBNAN/HALFNAN/QUADNAN. The stores are now unified,?rotm-style.?rotmgunifies only the values it actually writes: thep2 == 0early return still leavesD1/D2/X1untouched, and only theP[1..4]entries the flag selects are written.?rotgunifiescandsbeforeaandb, preserving the previous store order for an aliasing caller.One correction to the issue. The specific
drotgsign leak it reports (a = 0xfff8000000000000) does not reproduce on an8086-specialization build, which is what this repo builds on both CI platforms:f_absclears the NaN's sign before it reaches the arithmetic, so that input canonicalizes without the fix. The payload leak reported forsrotgdoes reproduce. The?rotgtests here therefore use signaling NaNs, which leak on this build (0x7ff4…came back as0x7ffc…, payload intact). The sign leak was presumably observed against the ARM-VFPv2 build.#35 —
test_cdotu_rounding_modesreads uninitialized stack at-O1An in-loop compound literal's lifetime ends with the iteration, and clang at
-O1sank the initializing stores for the secondcvecargument past the loop's back-edge, so the first iteration multiplied by stack garbage. The four operand literals are hoisted out asstaticarrays, as the rest of the file does.Testing
-O0,-O1and-O2(313 before, 12 new). Registration lint passes.master: the eight NaN tests fail, and the four?rotmgtermination tests hang until killed.srotmgexample from ?rotmg loops forever when d1 goes negative (reachable via negative d2 with q2 underflowing to -0) #33 was still running after 3 s, and the-O1assertion failed on every run.#33 and #34 share a commit because they touch overlapping hunks in the same four
?rotmgfiles.🤖 Generated with Claude Code