Skip to content
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

Rust 1.56.0+ no longer recognizes boundary checks as avoiding division overflow panic #99960

Closed
mqudsi opened this issue Jul 30, 2022 · 10 comments · Fixed by #109895
Closed

Rust 1.56.0+ no longer recognizes boundary checks as avoiding division overflow panic #99960

mqudsi opened this issue Jul 30, 2022 · 10 comments · Fixed by #109895
Assignees
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. I-heavy Issue: Problems and improvements with respect to binary size of generated code. I-slow Issue: Problems and improvements with respect to performance of generated code. P-low Low 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

@mqudsi
Copy link
Contributor

mqudsi commented Jul 30, 2022

The following code (contrived for demonstration purposes) correctly checks for and avoids a division overflow condition (i64::MIN input coerced to i64::MIN.abs() output) but a regression in rustc 1.56.0 (still in latest nightly and latest 1.62.0 release) causes the optimizer to no longer skip the checked division and panic branch:

pub fn checked_div_i64(dividend: i64, divisor: i64) -> Option<i64> {
    if dividend > i64::min_value() && divisor != 0 {
        Some(dividend / divisor)
    } else {
        None
    }
}

Godbolt link comparing 1.55.0 to 1.62.0

@rustbot label +regression-from-stable-to-stable +A-codegen +A-llvm +I-heavy +I-slow +T-compiler

Edit:

It might be worth adding some regression tests for this because it's happened and then was fixed a few times before (e.g. introduced in 1.47.0 and fixed in 1.48.0).

@mqudsi mqudsi added the C-bug Category: This is a bug. label Jul 30, 2022
@rustbot rustbot added A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. I-heavy Issue: Problems and improvements with respect to binary size of generated code. I-slow Issue: Problems and improvements with respect to performance of generated code. 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 Jul 30, 2022
@mqudsi
Copy link
Contributor Author

mqudsi commented Jul 30, 2022

This bisects to something between 2021-08-21 and 2021-08-22 in the range of a003591 to d3e2578, which includes #87570 (the upgrade to llvm 13), which is the most likely culprit.

@workingjubilee
Copy link
Member

workingjubilee commented Jul 30, 2022

The only difference in our unoptimized LLVMIR is that we now emit noundef, which enables other optimizations. Typically we do not add regression tests to Rust's test suite based purely on LLVM optimizations, and this regression does seem to be due to that. Even if we wanted one here, there's so many valid code emissions and optimizations for division, I'm not seeing a simple path forward for a regression test here.

But we will be upgrading LLVM soon (work has commenced in #99464).

@mqudsi
Copy link
Contributor Author

mqudsi commented Jul 30, 2022

Thanks for clarifying - I wasn't sure what was in-scope and what would purely be considered an upstream issue without any workarounds on our end. I should have checked --emit=llvm-ir and included that info in my original bug report - I've made a mental note to do that in the future.

I look forward to seeing if the migration to LLVM 15 will address this. In the meantime, I suppose this is what core::hint::unreachable_unchecked() was made for!

@nikic
Copy link
Contributor

nikic commented Jul 30, 2022

Still fails to optimize on current LLVM: https://llvm.godbolt.org/z/n7x4e9TKP It does work if the first logical and is replaced with a bitwise and, so something is missing logical and handling.

@nikic nikic self-assigned this Jul 30, 2022
@workingjubilee
Copy link
Member

It's a regression, so I see some value in tracking it on our issue tracker, I just don't see much value in a specific test for it because for the optimized forms of the LLVMIR, I thiiiink the only thing we could really do is check that bb6 is not present: https://godbolt.org/z/M9brfTcj9

@nikic
Copy link
Contributor

nikic commented Aug 2, 2022

Even this simple case doesn't get optimized: https://alive2.llvm.org/ce/z/jvVFVJ

@apiraino
Copy link
Contributor

apiraino commented Aug 9, 2022

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-low

@rustbot rustbot added P-low Low priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Aug 9, 2022
@nikic nikic added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Apr 3, 2023
@nikic
Copy link
Contributor

nikic commented Apr 3, 2023

Fixed since 1.68, though I don't know specifically what fixed it.

@apiraino
Copy link
Contributor

apiraino commented Apr 3, 2023

thanks! Tentatively closing the issue. Please @mqudsi report back if you still experience the issue

@mqudsi
Copy link
Contributor Author

mqudsi commented Apr 3, 2023

Thanks @nikic for the update and the codegen regression tests.

JohnTitor added a commit to JohnTitor/rust that referenced this issue Apr 11, 2023
bors added a commit to rust-lang-ci/rust that referenced this issue Apr 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. I-heavy Issue: Problems and improvements with respect to binary size of generated code. I-slow Issue: Problems and improvements with respect to performance of generated code. P-low Low 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.

5 participants