-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Pattern match incorrectly optimized out (bad range info handling in LLVM?) #26468
Comments
Perhaps it's a dup. The other two issues are broken with and without optimizations, though. This issue only fails with optimizations. |
Also: the |
The bug also happens without a #[inline(never)]
fn broken(mode: &Mode) -> u32 {
for _ in 0..1 {
if let Mode::Bar(BarMode::Bar1) = *mode { return 17 }
if let Mode::Foo(5) = *mode { return 19 }
}
return 42;
} |
Good point. Also, this only happens with opt-level=2 (not 0 or 3). |
cc @dotdash Further refinement of the test case: #[allow(dead_code)]
#[repr(u16)]
enum FooMode {
First = 0x1000,
Check = 0x1001,
Last = 0x100f,
}
#[allow(dead_code)]
#[repr(u16)]
enum BarMode {
First = 0x2000,
Check = 0x2001,
Last = 0x200f,
}
#[allow(dead_code)]
enum Mode {
Foo(FooMode),
Bar(BarMode),
}
#[inline(never)]
fn broken(mode: &Mode) -> u32 {
for _ in 0..1 {
if let Mode::Foo(FooMode::Check) = *mode { return 17 }
if let Mode::Bar(BarMode::Check) = *mode { return 19 }
}
return 42;
}
fn main() {
let mode = Mode::Bar(BarMode::Check);
assert_eq!(broken(&mode), 19);
} Changing I think this is an LLVM bug. It involves the match_case7: ; preds = %case_body2
%26 = bitcast %Mode* %21 to { i16, i16 }*
%27 = getelementptr inbounds { i16, i16 }, { i16, i16 }* %26, i32 0, i32 1
%28 = load i16, i16* %27, !range !3
switch i16 %28, label %match_else8 [
i16 4097, label %match_case9
]
...
match_case14: ; preds = %join
%32 = bitcast %Mode* %29 to { i16, i16 }*
%33 = getelementptr inbounds { i16, i16 }, { i16, i16 }* %32, i32 0, i32 1
%34 = load i16, i16* %33, !range !4
switch i16 %34, label %match_else15 [
i16 8193, label %match_case16
]
...
!3 = !{i16 4096, i16 4112}
!4 = !{i16 8192, i16 8208}
|
Thanks Ryan! Indeed LLVM replaces the load with another disregarding the range information. |
Patch landed upstream. |
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
The fix for rust-lang#26468 was made upstream and landed with the LLVM update in rust-lang#27076. Closes rust-lang#26468
Using yesterday's nightly, |
This test program should exit quietly, but with
rustc -O
, it instead fails the assertion:I also tested a really old 32-bit compiler, and it also failed:
This test case is reduced from #25919.
The text was updated successfully, but these errors were encountered: