Change:
The following code (contrived for demonstration purposes) correctly checks for and avoids a division overflow condition ( input coerced to 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: 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).
This bisects to something between 2021-08-21 and 2021-08-22 in the range of to , which includes (the upgrade to llvm 13), which is the most likely culprit.
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 ).
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 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 was made for!
Still fails to optimize on current LLVM: It does work if the first logical and is replaced with a bitwise and, so something is missing logical and handling.
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:
Even this simple case doesn't get optimized:
WG-prioritization assigning priority (). label -I-prioritize +P-low
Fixed since 1.68, though I don't know specifically what fixed it.
thanks! Tentatively closing the issue. Please report back if you still experience the issue
Thanks for the update and the codegen regression tests.

Discussion:
<ins> // compile-flags: -O // min-llvm-version: 16 #![crate_type = "lib"] #[no_mangle] pub fn all_zero(data: &[u64]) -> bool { // CHECK-LABEL: @all_zero( // CHECK: [[PHI:%.*]] = phi i1 // CHECK-NOT: phi i8 // CHECK-NOT: zext data.iter().copied().fold(true, |acc, x| acc & (x == 0)) } </ins>

<ins> // compile-flags: -O // min-llvm-version: 16 // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] #[no_mangle] pub fn test() -> usize { // CHECK-LABEL: @test( // CHECK: ret {{i64|i32}} 165 let values = [23, 16, 54, 3, 60, 9]; let mut acc = 0; for item in values { acc += item; } acc } </ins>

<ins> // compile-flags: -O // min-llvm-version: 16 // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] #[no_mangle] pub fn test(a: [i32; 10]) -> i32 { // CHECK-LABEL: @test( // CHECK: [[L1:%.+]] = load i32 // CHECK: [[L2:%.+]] = load i32 // CHECK: [[R:%.+]] = add i32 [[L1]], [[L2]] // CHECK: ret i32 [[R]] let mut sum = 0; for v in a.iter().skip(8) { sum += v; } sum } </ins>

<ins> // compile-flags: -O -C overflow-checks // min-llvm-version: 16 #![crate_type = "lib"] #[no_mangle] pub fn test(arr: &[u8], weight: u32) { // CHECK-LABEL: @test( // CHECK-NOT: panic let weight = weight.min(256 * 256 * 256); for x in arr { assert!(weight <= 256 * 256 * 256); let result = *x as u32 * weight; } } </ins>

<ins> // compile-flags: -O // min-llvm-version: 16 #![crate_type = "lib"] #[no_mangle] pub fn test(a: i32, b: i32) -> bool { // CHECK-LABEL: @test( // CHECK: ret i1 true let c1 = (a >= 0) && (a <= 10); let c2 = (b >= 0) && (b <= 20); if c1 & c2 { a + 100 != b } else { true } } </ins>

<ins> // compile-flags: -O // min-llvm-version: 16 #![crate_type = "lib"] #[no_mangle] pub fn test() -> u32 { // CHECK-LABEL: @test( // CHECK: ret i32 13 let s = [1, 2, 3, 4, 5, 6, 7]; let mut iter = s.iter(); let mut sum = 0; while let Some(_) = iter.next() { sum += iter.next().map_or(1, |&x| x) } sum } </ins>

<ins> // compile-flags: -O // min-llvm-version: 16 #![crate_type = "lib"] #[no_mangle] pub fn test(dividend: i64, divisor: i64) -> Option<i64> { // CHECK-LABEL: @test( // CHECK-NOT: panic if dividend > i64::min_value() && divisor != 0 { Some(dividend / divisor) } else { None } } </ins>