Add nan2008 target feature for MIPS#159526
Conversation
|
Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @nnethercote (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
Allow enabling the LLVM `nan2008` subtarget feature (IEEE 754-2008 NaN encoding) via `-Ctarget-feature` and `#[target_feature]`, gated behind the existing unstable `mips_target_feature` feature gate. This makes it possible to link against MIPS libraries built with GCC's `-mnan=2008`.
0edd123 to
180dde2
Compare
|
Here is some further context from Clang
So, more IEEE-compliant sounds good? But also this sounds like a target modifier maybe? cc @RalfJung |
|
Indeed, I believe this should be a target modifier. It is ABI breaking. Some background: NaNs generated by old (read: most) MIPS processors have the signaling/quiet bit set to zero if the NaN is quiet and non-zero if the NaN is signaling. The is contrary to most other architectures, which set the signaling/quiet bit to non-zero if the NaN is quiet, and to zero if the NaN is signaling. In IEEE754-2008, the behavior of x86 and most other architectures was made the recommended (not required!) encoding of the signaling/quiet state. MIPS64r3 added optional support for IEE754-2008 NaN signaling/quiet state encoding. It was made required in MIPS64r5. See https://web.archive.org/web/20170928005646/http://cdn2.imgtec.com/documentation/MD00083-2B-MIPS64INT-AFP-05.04.pdf, page 79 and page 84. Of the two relevant families of MIPS64 processors I'm aware (Cavium Octeon and Loongson's Godson), the later revisions of Godson implement this, the Octeon III is MIPS64r2 and does not. If the 2008 encoding is used, I'm not aware of many distros that actively support MIPS64, but for reference, Debian's MIPS64 targeted MIPS64r2 for Octeon III and Godson and did use the legacy encoding. I believe AOSC which only targets Godson uses 2008 encoding. So yeah, it would be good to have a target modifier for this, but a target feature would allow mixing code with different NaN signaling/quiet encodings, which I don't think should be allowed. |
AOSC uses the legacy encoding with ieee754=relaxed so some math operations actually behave erratically on Loongson 3A4000 (which uses 2008 encoding). As AOSC developers, I and @chenx97 have customly built systems with 2008 encoding on 3A4000 running but there's no consensus to switch the encoding for AOSC (AFAIK some users are running AOSC on Loongson 3A3000 which still uses legacy encoding).
The linker (at least BFD, unsure about LLD) will error out if the input object files use different NaN encodings. |
Yes, but Rust lets you toggle target features for individual functions, which would observe different NaN behavior. I couldn't come up with a very good example since the standard library actually explicitly doesn't make a lot of guarantees about signaling/quiet NaNs, so here's a bad attempt: fn compiled_with_default_nans() {
let some_number = some_function_compiled_with_2008_nans();
// No nan2008, this is no longer a quiet NaN from the
// perspective of this code
}
#[target_feature(enable = "nan2008")]
fn some_function_compiled_with_2008_nans() -> f64 {
// As per the docs, this is *guaranteed* to be a quiet NaN
// on conformant platforms (which we are in this function)
std::hint::black_box(f64::NAN)
} |
|
Also, it would be good to have support for nan2008 in |
Why not? The assumption for target features is that if they are enabled at compile time, then it is UB to run the program in an environment where the feature is not available, and therefore the macro is substituted with I have no idea what Okay, so... so far all target modifiers are hard-coded rustc flags ( We have an accepted MCP for a general "LLVM target features" target modifier: rust-lang/compiler-team#994. If that was implemented, If we want anything beyond that, a target modifier equivalent of "Rust target features" with sanity checks and So I'm afraid this is going to be neither fast nor trivial. Adding this flag in |
So the issue here is that from a distribution perspective, it is desirable to support as many CPUs as possible. To achieve this, what is done these days is that everything is compiled under the assumption of legacy NaNs and to avoid a performance hit, Most code will work just fine with this. Code that relies on specific quiet/signalling encoding does not. So suppose I would like to write a function that always returns a quiet NaN: The program is always compiled for legacy NaNs, even though at runtime it might run on a FPU which uses IEEE754-2008 NaN encoding. It would be no issue if it were possible to detect at runtime which encoding the FPU is using and then conditionally change the bit around as needed. // Note: I have no idea what f64::NAN behaves like on legacy NAN encoding on the moment, this
// is under the assumption that the same bits are returned no matter the platform
let quiet_nan = if is_mips64_target_feature_detected!("nan2008") {
// This is only a quiet NaN on processors that use IEEE754-2008 encoding
f64::NAN
} else {
// When we detect legacy encoding at runtime, we can clear the signaling/quiet bit
f64::from_bits(f64::NAN.to_bits() & !(1 << 51))
}I'd love for this not to be necessary, but not having any kind of runtime detection at all means programs will misbehave in practice with |
|
Does that runtime detection have to be built into the language though? |
|
Why wouldn't it be? I think this is a very desirable thing to check for and the macro already exists and provides all the nice extras like caching |
That sounds like plain UB to me, similar to how it's UB to run a program in a non-default rounding mode. So far the way you explained it I can't see any kind of coherent semantic that we could give to this, so I don't see a good way to provide any kind of Rust-level support. We definitely should not pretend that there's reasonable behavior here (e.g. by making normal-looking APIs work) when actually it's an ill-behaved mess. But one point that's not quite clear to me -- |
|
FWIW, from an LLVM perspective, we always assume that NaNs use the 754-2008 encoding. So technically speaking it is UB to ever run a program in legacy mode. I don't know if that can be used to cause actual unsoundness but I would assume so. It is therefore kind of pointless to try and do anything systematic for legacy mode, and certainly we shouldn't add any library API surface for this as that could be misinterpreted as things actually being well-behaved. What does the LLVM |
Yes. There is the Floating Point Implementation Register (FIR), in which bit 23 If |
|
Thanks. And what about this part?
|
|
I am indifferent to whether we make this a target feature or target modifier. I can see the arguments for either. But if we make it detectable, then it should in fact be valid to substitute it at compile time if we have been guaranteed it statically, just like it has been for other features. I do understand why the beach-house residents of this particular lake of fire like their homes simultaneously smoky yet well-lit. I just don't think we need to send them remittances of more fuel by altering our semantics of how target features work. For instance, we would have to also make |
Adds
nan2008to the allowed target features for MIPS, gated behind theexisting unstablemips_target_featuregate (tracking issue #150253), matching LLVM'snan2008subtarget feature (IEEE 754-2008 NaN encoding).Previously,
-Ctarget-feature=+nan2008producedwarning: unknown feature specified for '-Ctarget-feature': 'nan2008'and the feature was silently ignored. Since the prebuiltstdfor MIPS targets is compiled with legacy NaN encoding, linking against libraries built with GCC's-mnan=2008failed withld: failed to merge target specific data(mixing-mnan=legacyand-mnan=2008objects).With this change, users can enable the feature (together with
-Zbuild-stdto rebuildstdwith matching NaN encoding) to link such libraries.The feature name matches LLVM's directly, so no
to_llvm_featuresmapping is needed. Thetests/ui/check-cfg/target_feature.rsexpected output was re-blessed.Fixes #98999