Skip to content

Value differs between debug and release: 1.0 / ((-0.0) * black_box_zero) #102402

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

Closed
jruderman opened this issue Sep 28, 2022 · 11 comments · Fixed by #102517
Closed

Value differs between debug and release: 1.0 / ((-0.0) * black_box_zero) #102402

jruderman opened this issue Sep 28, 2022 · 11 comments · Fixed by #102517
Assignees
Labels
A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@jruderman
Copy link
Contributor

jruderman commented Sep 28, 2022

This code has differing behavior in debug and release (playground):

fn main() {
    let black_box_zero = (std::env::args().len() - 1) as f32;
    let result = 1.0 / ((-0.0) * black_box_zero);
    let expected = f32::NEG_INFINITY;
    assert_eq!(result, expected);
}

When compiled in debug mode (without optimizations), the program produces no output.

When compiled in release mode (with optimizations), the assertion fails:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `-inf`,
 right: `-inf`', src/main.rs:5:5

(This output doesn't make sense to me: how can they be unequal, but both negative infinity?)

@jruderman jruderman added the C-bug Category: This is a bug. label Sep 28, 2022
@jruderman
Copy link
Contributor Author

Here's another program with similar behavior, failing only in release. Not sure if it's the same issue.

fn main() {
    let black_box_one = (std::env::args().len()) as f32;
    let result = - (black_box_one / 0.0);
    let expected = f32::NEG_INFINITY;
    assert_eq!(result, expected);
}

@SNCPlay42
Copy link
Contributor

This function, based on the first code example, is misoptimized to unconditionally return false (godbolt):

pub fn foo(n: usize) -> bool {
    let black_box_zero = (n - 1) as f32;
    
    let result = 1.0 / ((-0.0) * black_box_zero);

    result == std::f32::NEG_INFINITY
}

This was not misoptimized before rustc 1.25, which upgraded LLVM to version 6.0. This appears to be a misoptimization by LLVM (Unless there's some allowed variability to do with the signs of zeroes that I'm not aware of?)

@rustbot label A-LLVM A-floating-point I-unsound T-compiler regression-from-stable-to-stable

@rustbot rustbot added A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Sep 28, 2022
@nbdd0121
Copy link
Contributor

This C code miscompiled under Clang as well: https://godbolt.org/z/bfqoGePW1.

Confirmed to be a LLVM bug.

@SNCPlay42
Copy link
Contributor

SNCPlay42 commented Sep 28, 2022

The second example does actually appear to be different - it doesn't miscompile until rustc 1.30 (godbolt) (which upgraded to LLVM 8).

@nikic
Copy link
Contributor

nikic commented Sep 28, 2022

Upstream issue: llvm/llvm-project#58046

@lukas-code
Copy link
Member

possibly related: #55131

@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Sep 29, 2022
@pnkfelix
Copy link
Member

pnkfelix commented Sep 30, 2022

T-compiler P-high review

@rustbot assign @nikic

(also, @Mark-Simulacrum notes that since upstream llvm/llvm-project#58046 is fixed now, this issue should eventually get resolved by either an LLVM upgrade or by cherry-picking the fix to Rust's LLVM fork.)

@jruderman
Copy link
Contributor Author

Does that fix take care of the second example?

bors added a commit to rust-lang-ci/rust that referenced this issue Sep 30, 2022
Update LLVM submodule

This merges in the current upstream release/15.x branch.

Fixes rust-lang#102402.
@bors bors closed this as completed in efbaa11 Sep 30, 2022
@jruderman
Copy link
Contributor Author

To answer my own question: both examples are fixed for me after updating rustc nightly from (9c56d9d 2022-09-29) to (8ce3204 2022-09-30)

@RalfJung
Copy link
Member

RalfJung commented Oct 5, 2022

Should we add a test for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-floating-point Area: Floating point numbers and arithmetic A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants