mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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:
@@ -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 }
|
||||
}
|
||||
Reference in New Issue
Block a user