You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SNaN and QNaN are swapped on mipsel and mips64el compared to most other architectures #68925
MIPS inverts the meaning of the signal/quiet bit in NaNs compared to every other platform. Rust and LLVM assume that platforms follow the standard convention, which can lead to surprising results. This issue tracks that mismatch, but it's not really actionable -- the best we can do is document this more clearly.
Original issue (likely outdated)
The following tests fail on mipsel and mips64el architectures while succeeding most others.
It succeeded on mipsel up to stable 1.36.0 rustc, and started failing in 1.37.0 and newer. I'll attempt to use cargo-bisect-rustc track down the exact nightly version that introduced the change (might take some time because it's a qemu vm that is rather slow).
#52897 (comment) was where the initial discussion started, but it seems to be worth a separate issue instead of creating noise there.
It looks as if the failing platforms have a signaling NAN (sNAN) in opposite to the succeeding ones with a quiet NAN (qNAN).
I didn't get cargo-bisect-rustc running properly, as it seems to be targeted at compile-time errors, and with the other attepmts (adding -- test, or running a script) it always told me that the regression was present in the start version already.
None the less, I bisected manually, and the first nightly which fails in my VM is nightly-2019-06-08-mipsel-unknown-linux-gnu - rustc 1.37.0-nightly (d132f544f 2019-06-07). d132f54 doesn't have anything to do with float numbers, but one of it's nearest ancestors, c5295ac, looks like it might be the commit that changed the behavior. @nagisa I'm not familiar with mips* hardware, but maybe newer processors changed behavior to match IEEE 754-2008 behavior? Before that, the signaling bit wasn't defined in the spec according to #52897 (comment).
The test where I discovered the problem fails for me on a qemu mipsel malta VM, as well as on build hosts provided by Debian (mipsel, mips64el), which are Rhino Labs UTM8 according to the wikipagesdescribing them. By incident it didn't get queued on any other type of machine.
Hmmm indeed c5295ac looks very much related. These are the changes in the compiler-builtins repo: rust-lang/compiler-builtins@0.1.15...0.1.16 . These are the changes in libm: rust-lang/libm@0ae4428...01bee72 . This is the PR that added Rust float min/max functions: #42430. I can't find anything suspicious, in fact it should just have moved the code from one place to another.
The next thing to investigate would probably be the codegen changes. This is the 1.36 output while this is the 1.37 output (both with optimizations enabled). IDK how one can get godbolt to show the fmaxf implementation. @silwol do you get the bug in release mode or only in debug mode?
@est31 Hadn't thought about checking whether it has something to do with build mode. Just tested, it only fails in debug build mode, and succeeds in release build mode.
changed the title [-]Different NaN types on mipsel and mips64el than on most other architectures[/-][+]SNaN and QNaN are swapped on mipsel and mips64el compared to most other architectures[/+]on Mar 18, 2026
#153343 should fix the concrete symptom of min/max behaving in odd ways, but the deeper issue of MIPS having swapped SNaN/QNaN representations is not really fixable without significant work on the LLVM side. For instance, pow/powi can still behave strangely, and if you check whether the NaNs you get back are signaling or not, you'll often see signaling NaNs (under the MIPS interpretation) where there should be quiet NaNs (namely any time an operation got const-folded).
@nagisa I'm not familiar with mips* hardware, but maybe newer processors changed behavior to match IEEE 754-2008 behavior? Before that, the signaling bit wasn't defined in the spec according to #52897 (comment).
Activity
est31 commentedon Feb 8, 2020
Note that this is a valid bug because it violates what that the docs of the
minfunction say:See also my comments in that thread for some investigations.
nagisa commentedon Feb 9, 2020
Both tests pass on actual mips64el hardware (Cavium Octeon II V0.1), as tested with
rustc 1.38.0 (625451e37 2019-09-23).EDIT: both with and without optimisations.
silwol commentedon Feb 10, 2020
I didn't get cargo-bisect-rustc running properly, as it seems to be targeted at compile-time errors, and with the other attepmts (adding
-- test, or running a script) it always told me that the regression was present in the start version already.None the less, I bisected manually, and the first nightly which fails in my VM is
nightly-2019-06-08-mipsel-unknown-linux-gnu - rustc 1.37.0-nightly (d132f544f 2019-06-07). d132f54 doesn't have anything to do with float numbers, but one of it's nearest ancestors, c5295ac, looks like it might be the commit that changed the behavior.@nagisa I'm not familiar with mips* hardware, but maybe newer processors changed behavior to match IEEE 754-2008 behavior? Before that, the signaling bit wasn't defined in the spec according to #52897 (comment).
The test where I discovered the problem fails for me on a qemu mipsel malta VM, as well as on build hosts provided by Debian (mipsel, mips64el), which are Rhino Labs UTM8 according to the wiki pages describing them. By incident it didn't get queued on any other type of machine.
est31 commentedon Feb 10, 2020
Hmmm indeed c5295ac looks very much related. These are the changes in the compiler-builtins repo: rust-lang/compiler-builtins@0.1.15...0.1.16 . These are the changes in libm: rust-lang/libm@0ae4428...01bee72 . This is the PR that added Rust float min/max functions: #42430. I can't find anything suspicious, in fact it should just have moved the code from one place to another.
The next thing to investigate would probably be the codegen changes. This is the 1.36 output while this is the 1.37 output (both with optimizations enabled). IDK how one can get godbolt to show the fmaxf implementation. @silwol do you get the bug in release mode or only in debug mode?
silwol commentedon Feb 10, 2020
@est31 Hadn't thought about checking whether it has something to do with build mode. Just tested, it only fails in debug build mode, and succeeds in release build mode.
est31 commentedon Feb 10, 2020
Thanks that's consistent with the output of godbolt I linked above, as there the compiler just optimizes out the checks.
[-]Different NaN types on mipsel and mips64el than on most other architectures[/-][+]SNaN and QNaN are swapped on mipsel and mips64el compared to most other architectures[/+]RalfJung commentedon Mar 18, 2026
#153343 should fix the concrete symptom of min/max behaving in odd ways, but the deeper issue of MIPS having swapped SNaN/QNaN representations is not really fixable without significant work on the LLVM side. For instance,
pow/powican still behave strangely, and if you check whether the NaNs you get back are signaling or not, you'll often see signaling NaNs (under the MIPS interpretation) where there should be quiet NaNs (namely any time an operation got const-folded).tgross35 commentedon Mar 18, 2026
This does exist as the NAN2008 flag on recent hardware, set in elf via
EF_MIPS_NAN2008. See https://www.sourceware.org/binutils/docs-2.25/as/MIPS-NaN-Encodings.html. I have no idea whether we ever emit it though.Per WebAssembly/design#976 (comment) it's R6+ that supports this, which apparently was pretty rare at the time that comment was written (2017).
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…
Rollup merge of rust-lang#157288 - RalfJung:mips-snan, r=ehuss,chenx9…