Skip to content

LLVM is allowed to... be creative... with NANs according to Rust float semantics #134417

Closed
@01mf02

Description

@01mf02

We have recently observed some very strange behaviour related to float handling, that seems to be linked to float parsing (01mf02/jaq#243).

Consider the following program:

fn main() {
    let t: f64 = "2.0".parse().unwrap();
    let z: f64 = "0.0".parse().unwrap();
    std::dbg!(t.to_bits(), z.to_bits());
    std::dbg!((t / z).total_cmp(&(z / z)));

    let t: f64 = 2.0;
    let z: f64 = 0.0;
    std::dbg!(t.to_bits(), z.to_bits());
    std::dbg!((t / z).total_cmp(&(z / z)));
}

This yields:

[src/main.rs:4:5] t.to_bits() = 4611686018427387904
[src/main.rs:4:5] z.to_bits() = 0
[src/main.rs:5:5] (t / z).total_cmp(&(z / z)) = Greater
[src/main.rs:9:5] t.to_bits() = 4611686018427387904
[src/main.rs:9:5] z.to_bits() = 0
[src/main.rs:10:5] (t / z).total_cmp(&(z / z)) = Less

Given that for both t and z, their bits are the same, I expected total_cmp to yield the same outputs; however, one yields Greater, the other yields Less!

I then refactored the program to an (IMO) equivalent one:

fn test(t: f64, z: f64) {
    std::dbg!(t.to_bits(), z.to_bits());
    std::dbg!((t / z).total_cmp(&(z / z)));
}

fn main() {
    test("2.0".parse().unwrap(), "0.0".parse().unwrap());
    test(2.0, 0.0);
}

Now, the output of total_cmp is the same!

[src/main.rs:2:5] t.to_bits() = 4611686018427387904
[src/main.rs:2:5] z.to_bits() = 0
[src/main.rs:3:5] (t / z).total_cmp(&(z / z)) = Greater
[src/main.rs:2:5] t.to_bits() = 4611686018427387904
[src/main.rs:2:5] z.to_bits() = 0
[src/main.rs:3:5] (t / z).total_cmp(&(z / z)) = Greater

This occurs both with cargo run and cargo run --release.

Could this be a compiler bug?

Meta

rustc --version --verbose:

rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: x86_64-unknown-linux-gnu
release: 1.83.0
LLVM version: 19.1.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-floating-pointArea: Floating point numbers and arithmeticC-discussionCategory: Discussion or questions that doesn't represent real issues.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions