-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Pattern match incorrectly optimized out (bad range info handling in LLVM?) #26468
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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: