summaryrefslogtreecommitdiffstats
path: root/tests/codegen/issues
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen/issues')
-rw-r--r--tests/codegen/issues/auxiliary/static_dllimport_aux.rs13
-rw-r--r--tests/codegen/issues/issue-101048.rs13
-rw-r--r--tests/codegen/issues/issue-101082.rs17
-rw-r--r--tests/codegen/issues/issue-101814.rs20
-rw-r--r--tests/codegen/issues/issue-103132.rs16
-rw-r--r--tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs16
-rw-r--r--tests/codegen/issues/issue-103327.rs18
-rw-r--r--tests/codegen/issues/issue-103840.rs9
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs22
-rw-r--r--tests/codegen/issues/issue-106369.rs15
-rw-r--r--tests/codegen/issues/issue-13018.rs11
-rw-r--r--tests/codegen/issues/issue-15953.rs29
-rw-r--r--tests/codegen/issues/issue-27130.rs21
-rw-r--r--tests/codegen/issues/issue-32031.rs23
-rw-r--r--tests/codegen/issues/issue-32364.rs18
-rw-r--r--tests/codegen/issues/issue-34634.rs16
-rw-r--r--tests/codegen/issues/issue-34947-pow-i32.rs13
-rw-r--r--tests/codegen/issues/issue-37945.rs35
-rw-r--r--tests/codegen/issues/issue-44056-macos-tls-align.rs28
-rw-r--r--tests/codegen/issues/issue-45222.rs63
-rw-r--r--tests/codegen/issues/issue-45466.rs15
-rw-r--r--tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs39
-rw-r--r--tests/codegen/issues/issue-47278.rs9
-rw-r--r--tests/codegen/issues/issue-47442.rs22
-rw-r--r--tests/codegen/issues/issue-56267-2.rs18
-rw-r--r--tests/codegen/issues/issue-56267.rs18
-rw-r--r--tests/codegen/issues/issue-56927.rs43
-rw-r--r--tests/codegen/issues/issue-58881.rs21
-rw-r--r--tests/codegen/issues/issue-59352.rs18
-rw-r--r--tests/codegen/issues/issue-69101-bounds-check.rs44
-rw-r--r--tests/codegen/issues/issue-73031.rs26
-rw-r--r--tests/codegen/issues/issue-73258.rs38
-rw-r--r--tests/codegen/issues/issue-73338-effecient-cmp.rs39
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs77
-rw-r--r--tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs17
-rw-r--r--tests/codegen/issues/issue-75525-bounds-checks.rs26
-rw-r--r--tests/codegen/issues/issue-75546.rs15
-rw-r--r--tests/codegen/issues/issue-75659.rs63
-rw-r--r--tests/codegen/issues/issue-75978.rs19
-rw-r--r--tests/codegen/issues/issue-77812.rs32
-rw-r--r--tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs15
-rw-r--r--tests/codegen/issues/issue-84268.rs23
-rw-r--r--tests/codegen/issues/issue-85872-multiple-reverse.rs20
-rw-r--r--tests/codegen/issues/issue-86106.rs62
-rw-r--r--tests/codegen/issues/issue-96274.rs17
-rw-r--r--tests/codegen/issues/issue-96497-slice-size-nowrap.rs29
-rw-r--r--tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs27
-rw-r--r--tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs19
-rw-r--r--tests/codegen/issues/issue-99960.rs15
49 files changed, 1242 insertions, 0 deletions
diff --git a/tests/codegen/issues/auxiliary/static_dllimport_aux.rs b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
new file mode 100644
index 000000000..afb0dc42f
--- /dev/null
+++ b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
@@ -0,0 +1,13 @@
+use std::sync::atomic::{AtomicPtr, Ordering};
+
+#[inline(always)]
+pub fn memrchr() {
+ fn detect() {}
+
+ static CROSS_CRATE_STATIC_ITEM: AtomicPtr<()> = AtomicPtr::new(detect as *mut ());
+
+ unsafe {
+ let fun = CROSS_CRATE_STATIC_ITEM.load(Ordering::SeqCst);
+ std::mem::transmute::<*mut (), fn()>(fun)()
+ }
+}
diff --git a/tests/codegen/issues/issue-101048.rs b/tests/codegen/issues/issue-101048.rs
new file mode 100644
index 000000000..efa4db93e
--- /dev/null
+++ b/tests/codegen/issues/issue-101048.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn all_zero(data: &[u64]) -> bool {
+ // CHECK-LABEL: @all_zero(
+ // CHECK: [[PHI:%.*]] = phi i1
+ // CHECK-NOT: phi i8
+ // CHECK-NOT: zext
+ data.iter().copied().fold(true, |acc, x| acc & (x == 0))
+}
diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs
new file mode 100644
index 000000000..2cbe99942
--- /dev/null
+++ b/tests/codegen/issues/issue-101082.rs
@@ -0,0 +1,17 @@
+// compile-flags: -O
+// min-llvm-version: 16
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test() -> usize {
+ // CHECK-LABEL: @test(
+ // CHECK: ret {{i64|i32}} 165
+ let values = [23, 16, 54, 3, 60, 9];
+ let mut acc = 0;
+ for item in values {
+ acc += item;
+ }
+ acc
+}
diff --git a/tests/codegen/issues/issue-101814.rs b/tests/codegen/issues/issue-101814.rs
new file mode 100644
index 000000000..13796352c
--- /dev/null
+++ b/tests/codegen/issues/issue-101814.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+// min-llvm-version: 16
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(a: [i32; 10]) -> i32 {
+ // CHECK-LABEL: @test(
+ // CHECK: [[L1:%.+]] = load i32
+ // CHECK: [[L2:%.+]] = load i32
+ // CHECK: [[R:%.+]] = add i32 [[L1]], [[L2]]
+ // CHECK: ret i32 [[R]]
+ let mut sum = 0;
+ for v in a.iter().skip(8) {
+ sum += v;
+ }
+
+ sum
+}
diff --git a/tests/codegen/issues/issue-103132.rs b/tests/codegen/issues/issue-103132.rs
new file mode 100644
index 000000000..cc87d7cd2
--- /dev/null
+++ b/tests/codegen/issues/issue-103132.rs
@@ -0,0 +1,16 @@
+// compile-flags: -O -C overflow-checks
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(arr: &[u8], weight: u32) {
+ // CHECK-LABEL: @test(
+ // CHECK-NOT: panic
+ let weight = weight.min(256 * 256 * 256);
+
+ for x in arr {
+ assert!(weight <= 256 * 256 * 256);
+ let result = *x as u32 * weight;
+ }
+}
diff --git a/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
new file mode 100644
index 000000000..a3499babe
--- /dev/null
+++ b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
@@ -0,0 +1,16 @@
+// compile-flags: -O -C debug-assertions=yes
+
+#![crate_type = "lib"]
+#![feature(strict_provenance)]
+
+#[no_mangle]
+pub fn test(src: *const u8, dst: *const u8) -> usize {
+ // CHECK-LABEL: @test(
+ // CHECK-NOT: panic
+ let src_usize = src.addr();
+ let dst_usize = dst.addr();
+ if src_usize > dst_usize {
+ return src_usize - dst_usize;
+ }
+ return 0;
+}
diff --git a/tests/codegen/issues/issue-103327.rs b/tests/codegen/issues/issue-103327.rs
new file mode 100644
index 000000000..cee00facc
--- /dev/null
+++ b/tests/codegen/issues/issue-103327.rs
@@ -0,0 +1,18 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(a: i32, b: i32) -> bool {
+ // CHECK-LABEL: @test(
+ // CHECK: ret i1 true
+ let c1 = (a >= 0) && (a <= 10);
+ let c2 = (b >= 0) && (b <= 20);
+
+ if c1 & c2 {
+ a + 100 != b
+ } else {
+ true
+ }
+}
diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
new file mode 100644
index 000000000..f19d7031b
--- /dev/null
+++ b/tests/codegen/issues/issue-103840.rs
@@ -0,0 +1,9 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+pub fn foo(t: &mut Vec<usize>) {
+ // CHECK-NOT: __rust_dealloc
+ let mut taken = std::mem::take(t);
+ taken.pop();
+ *t = taken;
+}
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
new file mode 100644
index 000000000..d54ac9e33
--- /dev/null
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -0,0 +1,22 @@
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
+// min-llvm-version: 15.0 # this test uses opaque pointer notation
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+#[no_mangle]
+pub fn outer_function(x: S, y: S) -> usize {
+ (#[inline(always)]|| {
+ let _z = x;
+ y.0[0]
+ })()
+}
+
+// Check that we do not attempt to load from the spilled arg before it is assigned to
+// when generating debuginfo.
+// CHECK-LABEL: @outer_function
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
+// CHECK-NOT: [[load:%.*]] = load ptr, ptr
+// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
diff --git a/tests/codegen/issues/issue-106369.rs b/tests/codegen/issues/issue-106369.rs
new file mode 100644
index 000000000..3fe7be4f1
--- /dev/null
+++ b/tests/codegen/issues/issue-106369.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// From <https://github.com/rust-lang/rust/issues/106369#issuecomment-1369095304>
+
+// CHECK-LABEL: @issue_106369(
+#[no_mangle]
+pub unsafe fn issue_106369(ptr: *const &i32) -> bool {
+ // CHECK-NOT: icmp
+ // CHECK: ret i1 true
+ // CHECK-NOT: icmp
+ Some(std::ptr::read(ptr)).is_some()
+}
diff --git a/tests/codegen/issues/issue-13018.rs b/tests/codegen/issues/issue-13018.rs
new file mode 100644
index 000000000..b70ea1f48
--- /dev/null
+++ b/tests/codegen/issues/issue-13018.rs
@@ -0,0 +1,11 @@
+// compile-flags: -O
+
+// A drop([...].clone()) sequence on an Rc should be a no-op
+// In particular, no call to __rust_dealloc should be emitted
+#![crate_type = "lib"]
+use std::rc::Rc;
+
+pub fn foo(t: &Rc<Vec<usize>>) {
+// CHECK-NOT: __rust_dealloc
+ drop(t.clone());
+}
diff --git a/tests/codegen/issues/issue-15953.rs b/tests/codegen/issues/issue-15953.rs
new file mode 100644
index 000000000..28d284289
--- /dev/null
+++ b/tests/codegen/issues/issue-15953.rs
@@ -0,0 +1,29 @@
+// Test that llvm generates `memcpy` for moving a value
+// inside a function and moving an argument.
+
+struct Foo {
+ x: Vec<i32>,
+}
+
+#[inline(never)]
+#[no_mangle]
+// CHECK: memcpy
+fn interior(x: Vec<i32>) -> Vec<i32> {
+ let Foo { x } = Foo { x: x };
+ x
+}
+
+#[inline(never)]
+#[no_mangle]
+// CHECK: memcpy
+fn exterior(x: Vec<i32>) -> Vec<i32> {
+ x
+}
+
+fn main() {
+ let x = interior(Vec::new());
+ println!("{:?}", x);
+
+ let x = exterior(Vec::new());
+ println!("{:?}", x);
+}
diff --git a/tests/codegen/issues/issue-27130.rs b/tests/codegen/issues/issue-27130.rs
new file mode 100644
index 000000000..e5ee94e1f
--- /dev/null
+++ b/tests/codegen/issues/issue-27130.rs
@@ -0,0 +1,21 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @trim_in_place
+#[no_mangle]
+pub fn trim_in_place(a: &mut &[u8]) {
+ while a.first() == Some(&42) {
+ // CHECK-NOT: slice_index_order_fail
+ *a = &a[1..];
+ }
+}
+
+// CHECK-LABEL: @trim_in_place2
+#[no_mangle]
+pub fn trim_in_place2(a: &mut &[u8]) {
+ while let Some(&42) = a.first() {
+ // CHECK-NOT: slice_index_order_fail
+ *a = &a[2..];
+ }
+}
diff --git a/tests/codegen/issues/issue-32031.rs b/tests/codegen/issues/issue-32031.rs
new file mode 100644
index 000000000..abef92c19
--- /dev/null
+++ b/tests/codegen/issues/issue-32031.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub struct F32(f32);
+
+// CHECK: define{{.*}}float @add_newtype_f32(float %a, float %b)
+#[inline(never)]
+#[no_mangle]
+pub fn add_newtype_f32(a: F32, b: F32) -> F32 {
+ F32(a.0 + b.0)
+}
+
+#[no_mangle]
+pub struct F64(f64);
+
+// CHECK: define{{.*}}double @add_newtype_f64(double %a, double %b)
+#[inline(never)]
+#[no_mangle]
+pub fn add_newtype_f64(a: F64, b: F64) -> F64 {
+ F64(a.0 + b.0)
+}
diff --git a/tests/codegen/issues/issue-32364.rs b/tests/codegen/issues/issue-32364.rs
new file mode 100644
index 000000000..85493a4bb
--- /dev/null
+++ b/tests/codegen/issues/issue-32364.rs
@@ -0,0 +1,18 @@
+// Test that `extern "stdcall"` is properly translated.
+
+// only-x86
+
+// compile-flags: -C no-prepopulate-passes
+
+struct Foo;
+
+impl Foo {
+// CHECK: define internal x86_stdcallcc void @{{.*}}foo{{.*}}()
+ #[inline(never)]
+ pub extern "stdcall" fn foo<T>() {
+ }
+}
+
+fn main() {
+ Foo::foo::<Foo>();
+}
diff --git a/tests/codegen/issues/issue-34634.rs b/tests/codegen/issues/issue-34634.rs
new file mode 100644
index 000000000..f53fa240c
--- /dev/null
+++ b/tests/codegen/issues/issue-34634.rs
@@ -0,0 +1,16 @@
+// Test that `wrapping_div` only checks divisor once.
+// This test checks that there is only a single compare against -1 and -1 is not present as a
+// switch case (the second check present until rustc 1.12).
+// This test also verifies that a single panic call is generated (for the division by zero case).
+
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f
+#[no_mangle]
+pub fn f(x: i32, y: i32) -> i32 {
+ // CHECK-COUNT-1: icmp eq i32 %y, -1
+ // CHECK-COUNT-1: panic
+ // CHECK-NOT: i32 -1, label
+ x.wrapping_div(y)
+}
diff --git a/tests/codegen/issues/issue-34947-pow-i32.rs b/tests/codegen/issues/issue-34947-pow-i32.rs
new file mode 100644
index 000000000..653da8e8b
--- /dev/null
+++ b/tests/codegen/issues/issue-34947-pow-i32.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @issue_34947
+#[no_mangle]
+pub fn issue_34947(x: i32) -> i32 {
+ // CHECK: mul
+ // CHECK-NEXT: mul
+ // CHECK-NEXT: mul
+ // CHECK-NEXT: ret
+ x.pow(5)
+}
diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs
new file mode 100644
index 000000000..4f386d335
--- /dev/null
+++ b/tests/codegen/issues/issue-37945.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O -Zmerge-functions=disabled
+// ignore-32bit LLVM has a bug with them
+// ignore-debug
+
+// Check that LLVM understands that `Iter` pointer is not null. Issue #37945.
+
+#![crate_type = "lib"]
+
+use std::slice::Iter;
+
+#[no_mangle]
+pub fn is_empty_1(xs: Iter<f32>) -> bool {
+// CHECK-LABEL: @is_empty_1(
+// CHECK-NEXT: start:
+// CHECK-NEXT: [[A:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
+// CHECK-NEXT: tail call void @llvm.assume(i1 [[A]])
+// The order between %xs.0 and %xs.1 on the next line doesn't matter
+// and different LLVM versions produce different order.
+// CHECK-NEXT: [[B:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
+// CHECK-NEXT: ret i1 [[B:%.*]]
+ {xs}.next().is_none()
+}
+
+#[no_mangle]
+pub fn is_empty_2(xs: Iter<f32>) -> bool {
+// CHECK-LABEL: @is_empty_2
+// CHECK-NEXT: start:
+// CHECK-NEXT: [[C:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null
+// CHECK-NEXT: tail call void @llvm.assume(i1 [[C]])
+// The order between %xs.0 and %xs.1 on the next line doesn't matter
+// and different LLVM versions produce different order.
+// CHECK-NEXT: [[D:%.*]] = icmp eq {{i32\*|ptr}} {{%xs.0, %xs.1|%xs.1, %xs.0}}
+// CHECK-NEXT: ret i1 [[D:%.*]]
+ xs.map(|&x| x).next().is_none()
+}
diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs
new file mode 100644
index 000000000..1a3923f1b
--- /dev/null
+++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs
@@ -0,0 +1,28 @@
+//
+// only-macos
+// no-system-llvm
+// compile-flags: -O
+
+#![crate_type = "rlib"]
+#![feature(thread_local)]
+
+// local_unnamed_addr does not appear when std is built with debug assertions.
+// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
+#[no_mangle]
+#[thread_local]
+static mut STATIC_VAR_1: [u32; 8] = [0; 8];
+
+// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
+#[no_mangle]
+#[thread_local]
+static mut STATIC_VAR_2: [u32; 8] = [4; 8];
+
+#[no_mangle]
+pub unsafe fn f(x: &mut [u32; 8]) {
+ std::mem::swap(x, &mut STATIC_VAR_1)
+}
+
+#[no_mangle]
+pub unsafe fn g(x: &mut [u32; 8]) {
+ std::mem::swap(x, &mut STATIC_VAR_2)
+}
diff --git a/tests/codegen/issues/issue-45222.rs b/tests/codegen/issues/issue-45222.rs
new file mode 100644
index 000000000..e9b05e648
--- /dev/null
+++ b/tests/codegen/issues/issue-45222.rs
@@ -0,0 +1,63 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+// verify that LLVM recognizes a loop involving 0..=n and will const-fold it.
+
+// Example from original issue #45222
+
+fn foo2(n: u64) -> u64 {
+ let mut count = 0;
+ for _ in 0..n {
+ for j in (0..=n).rev() {
+ count += j;
+ }
+ }
+ count
+}
+
+// CHECK-LABEL: @check_foo2
+#[no_mangle]
+pub fn check_foo2() -> u64 {
+ // CHECK: ret i64 500005000000000
+ foo2(100000)
+}
+
+// Simplified example of #45222
+//
+// Temporarily disabled in #68835 to fix a soundness hole.
+//
+// fn triangle_inc(n: u64) -> u64 {
+// let mut count = 0;
+// for j in 0 ..= n {
+// count += j;
+// }
+// count
+// }
+//
+// // COMMENTEDCHECK-LABEL: @check_triangle_inc
+// #[no_mangle]
+// pub fn check_triangle_inc() -> u64 {
+// // COMMENTEDCHECK: ret i64 5000050000
+// triangle_inc(100000)
+// }
+
+// Demo in #48012
+
+fn foo3r(n: u64) -> u64 {
+ let mut count = 0;
+ (0..n).for_each(|_| {
+ (0..=n).rev().for_each(|j| {
+ count += j;
+ })
+ });
+ count
+}
+
+// CHECK-LABEL: @check_foo3r
+#[no_mangle]
+pub fn check_foo3r() -> u64 {
+ // CHECK: ret i64 500050000000
+ foo3r(10000)
+}
diff --git a/tests/codegen/issues/issue-45466.rs b/tests/codegen/issues/issue-45466.rs
new file mode 100644
index 000000000..c79542767
--- /dev/null
+++ b/tests/codegen/issues/issue-45466.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @memzero
+// CHECK-NOT: store
+// CHECK: call void @llvm.memset
+// CHECK-NOT: store
+#[no_mangle]
+pub fn memzero(data: &mut [u8]) {
+ for i in 0..data.len() {
+ data[i] = 0;
+ }
+}
diff --git a/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
new file mode 100644
index 000000000..1daa213fc
--- /dev/null
+++ b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
@@ -0,0 +1,39 @@
+// This test case checks that slice::{r}position functions do not
+// prevent optimizing away bounds checks
+
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type="rlib"]
+
+// CHECK-LABEL: @test
+#[no_mangle]
+pub fn test(y: &[u32], x: &u32, z: &u32) -> bool {
+ let result = match y.iter().position(|a| a == x) {
+ Some(p) => Ok(p),
+ None => Err(()),
+ };
+
+ if let Ok(p) = result {
+ // CHECK-NOT: panic
+ y[p] == *z
+ } else {
+ false
+ }
+}
+
+// CHECK-LABEL: @rtest
+#[no_mangle]
+pub fn rtest(y: &[u32], x: &u32, z: &u32) -> bool {
+ let result = match y.iter().rposition(|a| a == x) {
+ Some(p) => Ok(p),
+ None => Err(()),
+ };
+
+ if let Ok(p) = result {
+ // CHECK-NOT: panic
+ y[p] == *z
+ } else {
+ false
+ }
+}
diff --git a/tests/codegen/issues/issue-47278.rs b/tests/codegen/issues/issue-47278.rs
new file mode 100644
index 000000000..9076274f4
--- /dev/null
+++ b/tests/codegen/issues/issue-47278.rs
@@ -0,0 +1,9 @@
+// -C no-prepopulate-passes
+#![crate_type="staticlib"]
+
+#[repr(C)]
+pub struct Foo(u64);
+
+// CHECK: define {{.*}} @foo(
+#[no_mangle]
+pub extern "C" fn foo(_: Foo) -> Foo { loop {} }
diff --git a/tests/codegen/issues/issue-47442.rs b/tests/codegen/issues/issue-47442.rs
new file mode 100644
index 000000000..6944336d3
--- /dev/null
+++ b/tests/codegen/issues/issue-47442.rs
@@ -0,0 +1,22 @@
+// check that we don't emit unneeded `resume` cleanup blocks for every
+// destructor.
+
+// CHECK-NOT: Unwind
+
+#![feature(test)]
+#![crate_type="rlib"]
+
+extern crate test;
+
+struct Foo {}
+
+impl Drop for Foo {
+ fn drop(&mut self) {
+ test::black_box(());
+ }
+}
+
+#[no_mangle]
+pub fn foo() {
+ let _foo = Foo {};
+}
diff --git a/tests/codegen/issues/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs
new file mode 100644
index 000000000..4dc9ebfeb
--- /dev/null
+++ b/tests/codegen/issues/issue-56267-2.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+ foo: u64,
+ bar: T,
+}
+
+// The load from bar.1 should have alignment 4. Not checking
+// other loads here, as the alignment will be platform-dependent.
+
+// CHECK: %{{.+}} = load i32, {{i32\*|ptr}} %{{.+}}, align 4
+#[no_mangle]
+pub fn test(x: Foo<(i32, i32)>) -> (i32, i32) {
+ x.bar
+}
diff --git a/tests/codegen/issues/issue-56267.rs b/tests/codegen/issues/issue-56267.rs
new file mode 100644
index 000000000..7bdd25779
--- /dev/null
+++ b/tests/codegen/issues/issue-56267.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+ foo: u64,
+ bar: T,
+}
+
+// The store writing to bar.1 should have alignment 4. Not checking
+// other stores here, as the alignment will be platform-dependent.
+
+// CHECK: store i32 [[TMP1:%.+]], {{i32\*|ptr}} [[TMP2:%.+]], align 4
+#[no_mangle]
+pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> {
+ Foo { foo: 0, bar: x }
+}
diff --git a/tests/codegen/issues/issue-56927.rs b/tests/codegen/issues/issue-56927.rs
new file mode 100644
index 000000000..044d72181
--- /dev/null
+++ b/tests/codegen/issues/issue-56927.rs
@@ -0,0 +1,43 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[repr(align(16))]
+pub struct S {
+ arr: [u32; 4],
+}
+
+// CHECK-LABEL: @test1
+// CHECK: store i32 0, {{i32\*|ptr}} %{{.+}}, align 16
+// CHECK: store i32 1, {{i32\*|ptr}} %{{.+}}, align 4
+// CHECK: store i32 2, {{i32\*|ptr}} %{{.+}}, align 8
+// CHECK: store i32 3, {{i32\*|ptr}} %{{.+}}, align 4
+#[no_mangle]
+pub fn test1(s: &mut S) {
+ s.arr[0] = 0;
+ s.arr[1] = 1;
+ s.arr[2] = 2;
+ s.arr[3] = 3;
+}
+
+// CHECK-LABEL: @test2
+// CHECK: store i32 4, {{i32\*|ptr}} %{{.+}}, align 4
+#[allow(unconditional_panic)]
+#[no_mangle]
+pub fn test2(s: &mut S) {
+ s.arr[usize::MAX / 4 + 1] = 4;
+}
+
+// CHECK-LABEL: @test3
+// CHECK: store i32 5, {{i32\*|ptr}} %{{.+}}, align 4
+#[no_mangle]
+pub fn test3(s: &mut S, i: usize) {
+ s.arr[i] = 5;
+}
+
+// CHECK-LABEL: @test4
+// CHECK: store i32 6, {{i32\*|ptr}} %{{.+}}, align 4
+#[no_mangle]
+pub fn test4(s: &mut S) {
+ s.arr = [6; 4];
+}
diff --git a/tests/codegen/issues/issue-58881.rs b/tests/codegen/issues/issue-58881.rs
new file mode 100644
index 000000000..00f8953d9
--- /dev/null
+++ b/tests/codegen/issues/issue-58881.rs
@@ -0,0 +1,21 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+//
+// only-x86_64
+// ignore-windows
+
+#![crate_type = "lib"]
+
+extern "C" {
+ fn variadic_fn(_: i32, ...);
+}
+
+#[repr(C)]
+struct Foo(u8);
+#[repr(C)]
+struct Bar(u64, u64, u64);
+
+// Ensure that emit arguments of the correct type.
+pub unsafe fn test_call_variadic() {
+ // CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, {{%Bar\*|ptr}} {{.*}})
+ variadic_fn(0, Foo(0), Bar(0, 0, 0))
+}
diff --git a/tests/codegen/issues/issue-59352.rs b/tests/codegen/issues/issue-59352.rs
new file mode 100644
index 000000000..d271fe027
--- /dev/null
+++ b/tests/codegen/issues/issue-59352.rs
@@ -0,0 +1,18 @@
+// This test is a mirror of mir-opt/issues/issue-59352.rs. The LLVM inliner doesn't inline
+// `char::method::is_digit()` and `char::method::to_digit()`, probably because of their size.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, mir-opt/issues/issue-59352.rs will need to be updated and this
+// test case should be removed as it will become redundant.
+
+// mir-opt-level=3 enables inlining and enables LLVM to optimize away the unreachable panic call.
+// compile-flags: -O -Z mir-opt-level=3
+
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: @num_to_digit
+#[no_mangle]
+pub fn num_to_digit(num: char) -> u32 {
+ // CHECK-NOT: panic
+ if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
diff --git a/tests/codegen/issues/issue-69101-bounds-check.rs b/tests/codegen/issues/issue-69101-bounds-check.rs
new file mode 100644
index 000000000..a3aca3a29
--- /dev/null
+++ b/tests/codegen/issues/issue-69101-bounds-check.rs
@@ -0,0 +1,44 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted in the loop when upfront slicing
+// ensures that the slices are big enough.
+// In particular, bounds checks were not always optimized out if the upfront
+// check was for a greater len than the loop requires.
+// (i.e. `already_sliced_no_bounds_check` was not always optimized even when
+// `already_sliced_no_bounds_check_exact` was)
+// CHECK-LABEL: @already_sliced_no_bounds_check
+#[no_mangle]
+pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+ // CHECK: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
+ for i in 0..1024 {
+ c[i] = a[i] ^ b[i];
+ }
+}
+
+// CHECK-LABEL: @already_sliced_no_bounds_check_exact
+#[no_mangle]
+pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
+ // CHECK: slice_end_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
+ for i in 0..1024 {
+ c[i] = a[i] ^ b[i];
+ }
+}
+
+// Make sure we're checking for the right thing: there can be a panic if the slice is too small.
+// CHECK-LABEL: @already_sliced_bounds_check
+#[no_mangle]
+pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+ // CHECK: slice_end_index_len_fail
+ // CHECK: panic_bounds_check
+ let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
+ for i in 0..1024 {
+ c[i] = a[i] ^ b[i];
+ }
+}
diff --git a/tests/codegen/issues/issue-73031.rs b/tests/codegen/issues/issue-73031.rs
new file mode 100644
index 000000000..a09c4bcfb
--- /dev/null
+++ b/tests/codegen/issues/issue-73031.rs
@@ -0,0 +1,26 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the unreachable `All::None` branch.
+
+pub enum All {
+ None,
+ Foo,
+ Bar,
+}
+
+// CHECK-LABEL: @issue_73031
+#[no_mangle]
+pub fn issue_73031(a: &mut All, q: i32) -> i32 {
+ *a = if q == 5 {
+ All::Foo
+ } else {
+ All::Bar
+ };
+ match *a {
+ // CHECK-NOT: panic
+ All::None => panic!(),
+ All::Foo => 1,
+ All::Bar => 2,
+ }
+}
diff --git a/tests/codegen/issues/issue-73258.rs b/tests/codegen/issues/issue-73258.rs
new file mode 100644
index 000000000..0134f929b
--- /dev/null
+++ b/tests/codegen/issues/issue-73258.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Adapted from <https://github.com/rust-lang/rust/issues/73258#issue-637346014>
+
+#[derive(Clone, Copy)]
+#[repr(u8)]
+pub enum Foo {
+ A, B, C, D,
+}
+
+// CHECK-LABEL: @issue_73258(
+#[no_mangle]
+pub unsafe fn issue_73258(ptr: *const Foo) -> Foo {
+ // CHECK-NOT: icmp
+ // CHECK-NOT: call
+ // CHECK-NOT: br
+ // CHECK-NOT: select
+
+ // CHECK: %[[R:.+]] = load i8
+ // CHECK-SAME: !range !
+
+ // CHECK-NOT: icmp
+ // CHECK-NOT: call
+ // CHECK-NOT: br
+ // CHECK-NOT: select
+
+ // CHECK: ret i8 %[[R]]
+
+ // CHECK-NOT: icmp
+ // CHECK-NOT: call
+ // CHECK-NOT: br
+ // CHECK-NOT: select
+ let k: Option<Foo> = Some(ptr.read());
+ return k.unwrap();
+}
diff --git a/tests/codegen/issues/issue-73338-effecient-cmp.rs b/tests/codegen/issues/issue-73338-effecient-cmp.rs
new file mode 100644
index 000000000..85c2bbfd0
--- /dev/null
+++ b/tests/codegen/issues/issue-73338-effecient-cmp.rs
@@ -0,0 +1,39 @@
+// This test checks that comparison operation
+// generated by #[derive(PartialOrd)]
+// doesn't contain jumps for C enums
+
+// compile-flags: -Copt-level=3
+
+#![crate_type="lib"]
+
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd)]
+pub enum Foo {
+ Zero,
+ One,
+ Two,
+}
+
+#[no_mangle]
+pub fn compare_less(a: Foo, b: Foo)->bool{
+ // CHECK-NOT: br {{.*}}
+ a < b
+}
+
+#[no_mangle]
+pub fn compare_le(a: Foo, b: Foo)->bool{
+ // CHECK-NOT: br {{.*}}
+ a <= b
+}
+
+#[no_mangle]
+pub fn compare_ge(a: Foo, b: Foo)->bool{
+ // CHECK-NOT: br {{.*}}
+ a >= b
+}
+
+#[no_mangle]
+pub fn compare_greater(a: Foo, b: Foo)->bool{
+ // CHECK-NOT: br {{.*}}
+ a > b
+}
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
new file mode 100644
index 000000000..8d07a67a1
--- /dev/null
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -0,0 +1,77 @@
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `position()` or `rposition()`.
+
+// CHECK-LABEL: @position_slice_to_no_bounds_check
+#[no_mangle]
+pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+ &s[..idx]
+ } else {
+ s
+ }
+}
+
+// CHECK-LABEL: @position_slice_from_no_bounds_check
+#[no_mangle]
+pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+ &s[idx..]
+ } else {
+ s
+ }
+}
+
+// CHECK-LABEL: @position_index_no_bounds_check
+#[no_mangle]
+pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+ s[idx]
+ } else {
+ 42
+ }
+}
+// CHECK-LABEL: @rposition_slice_to_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+ &s[..idx]
+ } else {
+ s
+ }
+}
+
+// CHECK-LABEL: @rposition_slice_from_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+ &s[idx..]
+ } else {
+ s
+ }
+}
+
+// CHECK-LABEL: @rposition_index_no_bounds_check
+#[no_mangle]
+pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
+ // CHECK-NOT: panic
+ // CHECK-NOT: slice_index_len_fail
+ if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+ s[idx]
+ } else {
+ 42
+ }
+}
diff --git a/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
new file mode 100644
index 000000000..1ad05906e
--- /dev/null
+++ b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
@@ -0,0 +1,17 @@
+// This test checks that bounds checks are elided when
+// index is part of a (x | y) < C style condition
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @get
+#[no_mangle]
+pub fn get(array: &[u8; 8], x: usize, y: usize) -> u8 {
+ if x > 7 || y > 7 {
+ 0
+ } else {
+ // CHECK-NOT: panic_bounds_check
+ array[y]
+ }
+}
diff --git a/tests/codegen/issues/issue-75525-bounds-checks.rs b/tests/codegen/issues/issue-75525-bounds-checks.rs
new file mode 100644
index 000000000..2d363d8f7
--- /dev/null
+++ b/tests/codegen/issues/issue-75525-bounds-checks.rs
@@ -0,0 +1,26 @@
+// Regression test for #75525, verifies that no bounds checks are generated.
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @f0
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f0(idx: usize, buf: &[u8; 10]) -> u8 {
+ if idx < 8 { buf[idx + 1] } else { 0 }
+}
+
+// CHECK-LABEL: @f1
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f1(idx: usize, buf: &[u8; 10]) -> u8 {
+ if idx > 5 && idx < 8 { buf[idx - 1] } else { 0 }
+}
+
+// CHECK-LABEL: @f2
+// CHECK-NOT: panic
+#[no_mangle]
+pub fn f2(idx: usize, buf: &[u8; 10]) -> u8 {
+ if idx > 5 && idx < 8 { buf[idx] } else { 0 }
+}
diff --git a/tests/codegen/issues/issue-75546.rs b/tests/codegen/issues/issue-75546.rs
new file mode 100644
index 000000000..470a9e040
--- /dev/null
+++ b/tests/codegen/issues/issue-75546.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the impossible `i == 0` check.
+
+// CHECK-LABEL: @issue_75546
+#[no_mangle]
+pub fn issue_75546() {
+ let mut i = 1u32;
+ while i < u32::MAX {
+ // CHECK-NOT: panic
+ if i == 0 { panic!(); }
+ i += 1;
+ }
+}
diff --git a/tests/codegen/issues/issue-75659.rs b/tests/codegen/issues/issue-75659.rs
new file mode 100644
index 000000000..9394868c0
--- /dev/null
+++ b/tests/codegen/issues/issue-75659.rs
@@ -0,0 +1,63 @@
+// This test checks that the call to memchr/slice_contains is optimized away
+// when searching in small slices.
+
+// compile-flags: -O -Zinline-mir=false
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @foo1
+#[no_mangle]
+pub fn foo1(x: u8, data: &[u8; 1]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ data.contains(&x)
+}
+
+// CHECK-LABEL: @foo2
+#[no_mangle]
+pub fn foo2(x: u8, data: &[u8; 2]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ data.contains(&x)
+}
+
+// CHECK-LABEL: @foo3
+#[no_mangle]
+pub fn foo3(x: u8, data: &[u8; 3]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ data.contains(&x)
+}
+
+// CHECK-LABEL: @foo4
+#[no_mangle]
+pub fn foo4(x: u8, data: &[u8; 4]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8
+#[no_mangle]
+pub fn foo8(x: u8, data: &[u8; 8]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8_i8
+#[no_mangle]
+pub fn foo8_i8(x: i8, data: &[i8; 8]) -> bool {
+ // CHECK-NOT: memchr
+ // CHECK-NOT: slice_contains
+ !data.contains(&x)
+}
+
+// Check that the general case isn't inlined
+// CHECK-LABEL: @foo80
+#[no_mangle]
+pub fn foo80(x: u8, data: &[u8; 80]) -> bool {
+ // CHECK: call core::slice::memchr
+ data.contains(&x)
+}
diff --git a/tests/codegen/issues/issue-75978.rs b/tests/codegen/issues/issue-75978.rs
new file mode 100644
index 000000000..f335e92c3
--- /dev/null
+++ b/tests/codegen/issues/issue-75978.rs
@@ -0,0 +1,19 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test() -> u32 {
+ // CHECK-LABEL: @test(
+ // CHECK: ret i32 13
+ let s = [1, 2, 3, 4, 5, 6, 7];
+
+ let mut iter = s.iter();
+ let mut sum = 0;
+ while let Some(_) = iter.next() {
+ sum += iter.next().map_or(1, |&x| x)
+ }
+
+ sum
+}
diff --git a/tests/codegen/issues/issue-77812.rs b/tests/codegen/issues/issue-77812.rs
new file mode 100644
index 000000000..4cc824145
--- /dev/null
+++ b/tests/codegen/issues/issue-77812.rs
@@ -0,0 +1,32 @@
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// Test that LLVM can eliminate the unreachable `Variant::Zero` branch.
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum Variant {
+ Zero,
+ One,
+ Two,
+}
+
+extern {
+ fn exf1();
+ fn exf2();
+}
+
+pub static mut GLOBAL: Variant = Variant::Zero;
+
+// CHECK-LABEL: @issue_77812
+#[no_mangle]
+pub unsafe fn issue_77812() {
+ let g = GLOBAL;
+ if g != Variant::Zero {
+ match g {
+ Variant::One => exf1(),
+ Variant::Two => exf2(),
+ // CHECK-NOT: panic
+ Variant::Zero => panic!(),
+ }
+ }
+}
diff --git a/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
new file mode 100644
index 000000000..0b6ab4f7e
--- /dev/null
+++ b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -C lto=thin -C prefer-dynamic=no
+// only-windows
+// aux-build:static_dllimport_aux.rs
+
+// Test that on Windows, when performing ThinLTO, we do not mark cross-crate static items with
+// dllimport because lld does not fix the symbol names for us.
+
+extern crate static_dllimport_aux;
+
+// CHECK-LABEL: @{{.+}}CROSS_CRATE_STATIC_ITEM{{.+}} =
+// CHECK-SAME: external local_unnamed_addr global %"{{.+}}AtomicPtr
+
+pub fn main() {
+ static_dllimport_aux::memrchr();
+}
diff --git a/tests/codegen/issues/issue-84268.rs b/tests/codegen/issues/issue-84268.rs
new file mode 100644
index 000000000..7ca195447
--- /dev/null
+++ b/tests/codegen/issues/issue-84268.rs
@@ -0,0 +1,23 @@
+// compile-flags: -O --crate-type=rlib
+#![feature(platform_intrinsics, repr_simd)]
+
+extern "platform-intrinsic" {
+ fn simd_fabs<T>(x: T) -> T;
+ fn simd_eq<T, U>(x: T, y: T) -> U;
+}
+
+#[repr(simd)]
+pub struct V([f32; 4]);
+
+#[repr(simd)]
+pub struct M([i32; 4]);
+
+#[no_mangle]
+// CHECK-LABEL: @is_infinite
+pub fn is_infinite(v: V) -> M {
+ // CHECK: fabs
+ // CHECK: cmp oeq
+ unsafe {
+ simd_eq(simd_fabs(v), V([f32::INFINITY; 4]))
+ }
+}
diff --git a/tests/codegen/issues/issue-85872-multiple-reverse.rs b/tests/codegen/issues/issue-85872-multiple-reverse.rs
new file mode 100644
index 000000000..591a1aca7
--- /dev/null
+++ b/tests/codegen/issues/issue-85872-multiple-reverse.rs
@@ -0,0 +1,20 @@
+// min-llvm-version: 15.0.0
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn u16_be_to_arch(mut data: [u8; 2]) -> [u8; 2] {
+ // CHECK-LABEL: @u16_be_to_arch
+ // CHECK: @llvm.bswap.i16
+ data.reverse();
+ data
+}
+
+#[no_mangle]
+pub fn u32_be_to_arch(mut data: [u8; 4]) -> [u8; 4] {
+ // CHECK-LABEL: @u32_be_to_arch
+ // CHECK: @llvm.bswap.i32
+ data.reverse();
+ data
+}
diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs
new file mode 100644
index 000000000..9ccbcb24f
--- /dev/null
+++ b/tests/codegen/issues/issue-86106.rs
@@ -0,0 +1,62 @@
+// min-llvm-version: 15.0
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled
+
+// The below two functions ensure that both `String::new()` and `"".to_string()`
+// produce the identical code.
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: define void @string_new
+#[no_mangle]
+pub fn string_new() -> String {
+ // CHECK-NOT: load i8
+ // CHECK: store i{{32|64}}
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store ptr
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: ret void
+ String::new()
+}
+
+// CHECK-LABEL: define void @empty_to_string
+#[no_mangle]
+pub fn empty_to_string() -> String {
+ // CHECK-NOT: load i8
+ // CHECK: store i{{32|64}}
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store ptr
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: ret void
+ "".to_string()
+}
+
+// The below two functions ensure that both `vec![]` and `vec![].clone()`
+// produce the identical code.
+
+// CHECK-LABEL: @empty_vec
+#[no_mangle]
+pub fn empty_vec() -> Vec<u8> {
+ // CHECK: store i{{32|64}}
+ // CHECK-NOT: load i8
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store ptr
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: ret void
+ vec![]
+}
+
+// CHECK-LABEL: @empty_vec_clone
+#[no_mangle]
+pub fn empty_vec_clone() -> Vec<u8> {
+ // CHECK: store i{{32|64}}
+ // CHECK-NOT: load i8
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store ptr
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: store i{{32|64}}
+ // CHECK-NEXT: ret void
+ vec![].clone()
+}
diff --git a/tests/codegen/issues/issue-96274.rs b/tests/codegen/issues/issue-96274.rs
new file mode 100644
index 000000000..28bfcce0d
--- /dev/null
+++ b/tests/codegen/issues/issue-96274.rs
@@ -0,0 +1,17 @@
+// min-llvm-version: 15.0
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(inline_const)]
+
+use std::mem::MaybeUninit;
+
+pub fn maybe_uninit() -> [MaybeUninit<u8>; 3000] {
+ // CHECK-NOT: memset
+ [MaybeUninit::uninit(); 3000]
+}
+
+pub fn maybe_uninit_const<T>() -> [MaybeUninit<T>; 8192] {
+ // CHECK-NOT: memset
+ [const { MaybeUninit::uninit() }; 8192]
+}
diff --git a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
new file mode 100644
index 000000000..0413ed6b2
--- /dev/null
+++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
@@ -0,0 +1,29 @@
+// This test case checks that LLVM is aware that computing the size of a slice cannot wrap.
+// The possibility of wrapping results in an additional branch when dropping boxed slices
+// in some situations, see https://github.com/rust-lang/rust/issues/96497#issuecomment-1112865218
+
+// compile-flags: -O
+// min-llvm-version: 15.0
+
+#![crate_type="lib"]
+
+// CHECK-LABEL: @simple_size_of_nowrap
+#[no_mangle]
+pub fn simple_size_of_nowrap(x: &[u32]) -> usize {
+ // Make sure the shift used to compute the size has a nowrap flag.
+
+ // CHECK: [[A:%.*]] = shl nsw {{.*}}, 2
+ // CHECK-NEXT: ret {{.*}} [[A]]
+ core::mem::size_of_val(x)
+}
+
+// CHECK-LABEL: @drop_write
+#[no_mangle]
+pub fn drop_write(mut x: Box<[u32]>) {
+ // Check that this write is optimized out.
+ // This depends on the size calculation not wrapping,
+ // since otherwise LLVM can't tell that the memory is always deallocated if the slice len > 0.
+
+ // CHECK-NOT: store i32 42
+ x[1] = 42;
+}
diff --git a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
new file mode 100644
index 000000000..12ace5fff
--- /dev/null
+++ b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
@@ -0,0 +1,27 @@
+// This test checks that temporaries for indirectly-passed arguments get lifetime markers.
+
+// compile-flags: -O -C no-prepopulate-passes -Zmir-opt-level=0
+
+#![crate_type = "lib"]
+
+extern "Rust" {
+ fn f(x: [u8; 1024]);
+}
+
+const A: [u8; 1024] = [0; 1024];
+
+// CHECK-LABEL: @const_arg_indirect
+#[no_mangle]
+pub unsafe fn const_arg_indirect() {
+ // Ensure that the live ranges for the two argument temporaries don't overlap.
+
+ // CHECK: call void @llvm.lifetime.start
+ // CHECK: call void @f
+ // CHECK: call void @llvm.lifetime.end
+ // CHECK: call void @llvm.lifetime.start
+ // CHECK: call void @f
+ // CHECK: call void @llvm.lifetime.end
+
+ f(A);
+ f(A);
+}
diff --git a/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
new file mode 100644
index 000000000..7da29cd79
--- /dev/null
+++ b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
@@ -0,0 +1,19 @@
+// min-llvm-version: 15.0.0
+// ignore-debug: The debug assertions get in the way
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// There should be no calls to panic / len_mismatch_fail.
+
+#[no_mangle]
+pub fn test(a: &mut [u8], offset: usize, bytes: &[u8]) {
+ // CHECK-LABEL: @test(
+ // CHECK-NOT: call
+ // CHECK: call void @llvm.memcpy
+ // CHECK-NOT: call
+ // CHECK: }
+ if let Some(dst) = a.get_mut(offset..offset + bytes.len()) {
+ dst.copy_from_slice(bytes);
+ }
+}
diff --git a/tests/codegen/issues/issue-99960.rs b/tests/codegen/issues/issue-99960.rs
new file mode 100644
index 000000000..e9c9367fa
--- /dev/null
+++ b/tests/codegen/issues/issue-99960.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// min-llvm-version: 16
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test(dividend: i64, divisor: i64) -> Option<i64> {
+ // CHECK-LABEL: @test(
+ // CHECK-NOT: panic
+ if dividend > i64::min_value() && divisor != 0 {
+ Some(dividend / divisor)
+ } else {
+ None
+ }
+}