about summary refs log tree commit diff
path: root/tests/codegen-llvm
diff options
context:
space:
mode:
authorokaneco <47607823+okaneco@users.noreply.github.com>2025-08-14 00:59:11 -0400
committerokaneco <47607823+okaneco@users.noreply.github.com>2025-08-20 22:29:45 -0400
commit9e28de2720e658b015e4609001bad7b11eac1e6d (patch)
treeefa795889fe241a20d077c4a349b812c0ecafddb /tests/codegen-llvm
parent3672a55b7cfd0a12e7097197b6242872473ffaa7 (diff)
downloadrust-9e28de2720e658b015e4609001bad7b11eac1e6d.tar.gz
rust-9e28de2720e658b015e4609001bad7b11eac1e6d.zip
Add codegen regression tests
Most of these regressions concern elimination of panics and bounds
checks that were fixed upstream by LLVM.
Diffstat (limited to 'tests/codegen-llvm')
-rw-r--r--tests/codegen-llvm/issues/and-masked-comparison-131162.rs17
-rw-r--r--tests/codegen-llvm/issues/assert-for-loop-bounds-check-71997.rs18
-rw-r--r--tests/codegen-llvm/issues/elided-division-by-zero-check-74917.rs13
-rw-r--r--tests/codegen-llvm/issues/for-loop-inner-assert-91109.rs18
-rw-r--r--tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs31
-rw-r--r--tests/codegen-llvm/issues/matches-logical-or-141497.rs25
-rw-r--r--tests/codegen-llvm/issues/no-bounds-check-after-assert-110971.rs14
-rw-r--r--tests/codegen-llvm/issues/no-panic-for-pop-after-assert-71257.rs19
-rw-r--r--tests/codegen-llvm/issues/num-is-digit-to-digit-59352.rs14
-rw-r--r--tests/codegen-llvm/issues/slice-index-bounds-check-80075.rs13
10 files changed, 182 insertions, 0 deletions
diff --git a/tests/codegen-llvm/issues/and-masked-comparison-131162.rs b/tests/codegen-llvm/issues/and-masked-comparison-131162.rs
new file mode 100644
index 00000000000..bdf021092fd
--- /dev/null
+++ b/tests/codegen-llvm/issues/and-masked-comparison-131162.rs
@@ -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)
+}
diff --git a/tests/codegen-llvm/issues/assert-for-loop-bounds-check-71997.rs b/tests/codegen-llvm/issues/assert-for-loop-bounds-check-71997.rs
new file mode 100644
index 00000000000..a0c64d607a8
--- /dev/null
+++ b/tests/codegen-llvm/issues/assert-for-loop-bounds-check-71997.rs
@@ -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
+}
diff --git a/tests/codegen-llvm/issues/elided-division-by-zero-check-74917.rs b/tests/codegen-llvm/issues/elided-division-by-zero-check-74917.rs
new file mode 100644
index 00000000000..9e890e14852
--- /dev/null
+++ b/tests/codegen-llvm/issues/elided-division-by-zero-check-74917.rs
@@ -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 }
+}
diff --git a/tests/codegen-llvm/issues/for-loop-inner-assert-91109.rs b/tests/codegen-llvm/issues/for-loop-inner-assert-91109.rs
new file mode 100644
index 00000000000..bffbcd7d069
--- /dev/null
+++ b/tests/codegen-llvm/issues/for-loop-inner-assert-91109.rs
@@ -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;
+        }
+    }
+}
diff --git a/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs b/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs
new file mode 100644
index 00000000000..4d3fa4993ef
--- /dev/null
+++ b/tests/codegen-llvm/issues/iter-max-no-unwrap-failed-129583.rs
@@ -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()
+}
diff --git a/tests/codegen-llvm/issues/matches-logical-or-141497.rs b/tests/codegen-llvm/issues/matches-logical-or-141497.rs
new file mode 100644
index 00000000000..348f62096a5
--- /dev/null
+++ b/tests/codegen-llvm/issues/matches-logical-or-141497.rs
@@ -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)
+}
diff --git a/tests/codegen-llvm/issues/no-bounds-check-after-assert-110971.rs b/tests/codegen-llvm/issues/no-bounds-check-after-assert-110971.rs
new file mode 100644
index 00000000000..aa4002f176d
--- /dev/null
+++ b/tests/codegen-llvm/issues/no-bounds-check-after-assert-110971.rs
@@ -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]
+}
diff --git a/tests/codegen-llvm/issues/no-panic-for-pop-after-assert-71257.rs b/tests/codegen-llvm/issues/no-panic-for-pop-after-assert-71257.rs
new file mode 100644
index 00000000000..68877c28d6c
--- /dev/null
+++ b/tests/codegen-llvm/issues/no-panic-for-pop-after-assert-71257.rs
@@ -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()
+}
diff --git a/tests/codegen-llvm/issues/num-is-digit-to-digit-59352.rs b/tests/codegen-llvm/issues/num-is-digit-to-digit-59352.rs
new file mode 100644
index 00000000000..1d23eb2cdf9
--- /dev/null
+++ b/tests/codegen-llvm/issues/num-is-digit-to-digit-59352.rs
@@ -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 }
+}
diff --git a/tests/codegen-llvm/issues/slice-index-bounds-check-80075.rs b/tests/codegen-llvm/issues/slice-index-bounds-check-80075.rs
new file mode 100644
index 00000000000..ecb5eb787c7
--- /dev/null
+++ b/tests/codegen-llvm/issues/slice-index-bounds-check-80075.rs
@@ -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 }
+}