Skip to content

Commit b109232

Browse files
committed
Add codegen regression tests
Most of these regressions concern elimination of panics and bounds checks that were fixed upstream by LLVM.
1 parent 3672a55 commit b109232

11 files changed

+193
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ compile-flags: -Copt-level=3
2+
//@ min-llvm-version: 20
3+
4+
#![crate_type = "lib"]
5+
6+
// CHECK-LABEL: @issue_131162
7+
#[no_mangle]
8+
pub fn issue_131162(a1: usize, a2: usize) -> bool {
9+
const MASK: usize = 1;
10+
11+
// CHECK-NOT: xor
12+
// CHECK-NOT: trunc
13+
// CHECK-NOT: and i1
14+
// CHECK: icmp
15+
// CHECK-NEXT: ret
16+
(a1 & !MASK) == (a2 & !MASK) && (a1 & MASK) == (a2 & MASK)
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Tests that there's no bounds check within for-loop after asserting that
2+
// the range start and end are within bounds.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @no_bounds_check_after_assert
9+
#[no_mangle]
10+
fn no_bounds_check_after_assert(slice: &[u64], start: usize, end: usize) -> u64 {
11+
// CHECK-NOT: panic_bounds_check
12+
let mut total = 0;
13+
assert!(start < end && start < slice.len() && end <= slice.len());
14+
for i in start..end {
15+
total += slice[i];
16+
}
17+
total
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Tests that there is no check for dividing by zero since the
2+
// denominator, `(x - y)`, will always be greater than 0 since `x > y`.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @issue_74917
9+
#[no_mangle]
10+
pub fn issue_74917(x: u16, y: u16) -> u16 {
11+
// CHECK-NOT: panic
12+
if x > y { 100 / (x - y) } else { 100 }
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Tests that there's no bounds check for the inner loop after the assert.
2+
3+
//@ compile-flags: -Copt-level=3
4+
5+
#![crate_type = "lib"]
6+
7+
// CHECK-LABEL: @zero
8+
#[no_mangle]
9+
pub fn zero(d: &mut [Vec<i32>]) {
10+
// CHECK-NOT: panic_bounds_check
11+
let n = d.len();
12+
for i in 0..n {
13+
assert!(d[i].len() == n);
14+
for j in 0..n {
15+
d[i][j] = 0;
16+
}
17+
}
18+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Tests that `unwrap` is optimized out when the slice has a known length.
2+
// The iterator may unroll for values smaller than a certain threshold so we
3+
// use a larger value to prevent unrolling.
4+
5+
//@ compile-flags: -Copt-level=3
6+
//@ min-llvm-version: 20
7+
8+
#![crate_type = "lib"]
9+
10+
// CHECK-LABEL: @infallible_max_not_unrolled
11+
#[no_mangle]
12+
pub fn infallible_max_not_unrolled(x: &[u8; 1024]) -> u8 {
13+
// CHECK-NOT: panic
14+
// CHECK-NOT: unwrap_failed
15+
*x.iter().max().unwrap()
16+
}
17+
18+
// CHECK-LABEL: @infallible_max_unrolled
19+
#[no_mangle]
20+
pub fn infallible_max_unrolled(x: &[u8; 10]) -> u8 {
21+
// CHECK-NOT: panic
22+
// CHECK-NOT: unwrap_failed
23+
*x.iter().max().unwrap()
24+
}
25+
26+
// CHECK-LABEL: @may_panic_max
27+
#[no_mangle]
28+
pub fn may_panic_max(x: &[u8]) -> u8 {
29+
// CHECK: unwrap_failed
30+
*x.iter().max().unwrap()
31+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Tests that `matches!` optimizes the same as
2+
// `f == FrameType::Inter || f == FrameType::Switch`.
3+
4+
//@ compile-flags: -Copt-level=3
5+
//@ min-llvm-version: 21
6+
7+
#![crate_type = "lib"]
8+
9+
#[derive(Clone, Copy, PartialEq, Eq)]
10+
pub enum FrameType {
11+
Key = 0,
12+
Inter = 1,
13+
Intra = 2,
14+
Switch = 3,
15+
}
16+
17+
// CHECK-LABEL: @is_inter_or_switch
18+
#[no_mangle]
19+
pub fn is_inter_or_switch(f: FrameType) -> bool {
20+
// CHECK-NOT: ADD
21+
matches!(f, FrameType::Inter | FrameType::Switch)
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Tests that the slice access for `j` doesn't have a bounds check panic after
2+
// being asserted as less than half of the slice length.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @check_only_assert_panic
9+
#[no_mangle]
10+
pub fn check_only_assert_panic(arr: &[u32], j: usize) -> u32 {
11+
// CHECK-NOT: panic_bounds_check
12+
assert!(j < arr.len() / 2);
13+
arr[j]
14+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Tests that the `unwrap` branch is optimized out from the `pop` since the
2+
// length has already been validated.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
pub enum Foo {
9+
First(usize),
10+
Second(usize),
11+
}
12+
13+
// CHECK-LABEL: @check_only_one_panic
14+
#[no_mangle]
15+
pub fn check_only_one_panic(v: &mut Vec<Foo>) -> Foo {
16+
// CHECK-COUNT-1: call{{.+}}panic
17+
assert!(v.len() == 1);
18+
v.pop().unwrap()
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Tests that there's no panic on unwrapping `to_digit` call after checking
2+
// with `is_digit`.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @num_to_digit_slow
9+
#[no_mangle]
10+
pub fn num_to_digit_slow(num: char) -> u32 {
11+
// CHECK-NOT: br
12+
// CHECK-NOT: panic
13+
if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Tests that no bounds check panic is generated for `j` since
2+
// `j <= i < data.len()`.
3+
4+
//@ compile-flags: -Copt-level=3
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @issue_80075
9+
#[no_mangle]
10+
pub fn issue_80075(data: &[u8], i: usize, j: usize) -> u8 {
11+
// CHECK-NOT: panic_bounds_check
12+
if i < data.len() && j <= i { data[j] } else { 0 }
13+
}

0 commit comments

Comments
 (0)