-
Notifications
You must be signed in to change notification settings - Fork 13.4k
f64::round doesn't work properly on arm-unknown-linux-gnueabi #122294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
With
With optimizations enabled:
I'm guessing that this is an LLVM backend-specific issue, but I don't have any 32-bit ARM on hand to test these. |
Realizing that the problem is more likely related to compiling the float formatting machinery. We've for sure found miscompiles in there before. |
I also looked into assembler, but I still didn't understand where the
I'm reproducing this issue on Raspberry Pi Zero, but I think this bug can be reproduced in Qemu.
Literally on the same day, while dealing with f64::round, I encountered another bug: #46950. Another broken floating point operation that can also be workarounded with a naive implementation. Can I help with this bug? |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-high |
Maybe. Usually the best thing to do here is to minimize the reproducer. The fact that your reproducer uses the standard library formatting is a bit vexing, because if that's where the code pattern is that's being miscompiled, you have a lot of code to start from. There are other formatting crates, so I'd see if this reproduces with one of them. It's pretty easy to find a handful of them by searching |
I decided not to try to make a minimal repro. I was afraid that any “my” code could introduce new bugs. And I went looking for a very simple solution, where it would be clearly visible that the problem was in f64::round(). I abandoned std format and used As a result, I wrote this repro: Codefn main() {
// Debug fail, release ok:
// print_float(15.44f64);
// print_float(15.44f64.round());
// Debug fail, release fail:
// print_float(std::hint::black_box(get_float()));
// print_float(std::hint::black_box(get_float()).round());
}
#[inline(never)]
fn get_float() -> f64 {
15.44
}
#[inline(never)]
fn print_float(value: f64) {
let mut buffer = ryu::Buffer::new();
let printed = buffer.format(value);
print_str(printed);
print_str("\n");
}
#[inline(always)]
fn print_str(s: &str) {
unsafe { libc::write(1, s.as_ptr() as _, s.len()) };
} The difference between the first two lines and the second two lines is that in the first case Rust optimizes To be even more confident, I abandoned rye altogether and simply decided to print the bytes of the rounded float: No float format codefn main() {
print_float(std::hint::black_box(get_float()));
print_float(std::hint::black_box(get_float()).round());
}
#[inline(never)]
fn get_float() -> f64 {
15.44
}
#[inline(never)]
fn print_float(value: f64) {
let printed = format!("{:X?}", value.to_ne_bytes());
print_str(&printed);
print_str("\n");
}
#[inline(always)]
fn print_str(s: &str) {
unsafe { libc::write(1, s.as_ptr() as _, s.len()) };
} And got zeroes:
If necessary, I will post this code on Github and attach binaries. I don't know what the problem is with |
P-high pre-triage: tagging this as |
I'm cross-compiling for target
arm-unknown-linux-gnueabi
, and I encountered thatf64::round()
does not work correctly. I tried this code:I expected to see:
But instead, in the debug build I see:
In the release build, as a rule, the output is correct, but sometimes
f64::round()
returning 0 or 1 instead of the correct rounding. I can't reliably reproduce this bug in release build.I build this code in docker container. See more details under the spoiler.
Build details
I build code with this command:
Dockerfile
:Cargo.toml
:.cargo/config.toml
:binaries.tar.gz
source.tar.gz
Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: