Add codegen regression tests

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