summaryrefslogtreecommitdiffstats
path: root/src/test/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/codegen')
-rw-r--r--src/test/codegen/abi-efiapi.rs2
-rw-r--r--src/test/codegen/async-fn-debug-awaitee-field.rs8
-rw-r--r--src/test/codegen/auxiliary/extern_decl.rs11
-rw-r--r--src/test/codegen/auxiliary/static_dllimport_aux.rs13
-rw-r--r--src/test/codegen/avr/avr-func-addrspace.rs16
-rw-r--r--src/test/codegen/dllimports/main.rs13
-rw-r--r--src/test/codegen/enum-bounds-check-derived-idx.rs6
-rw-r--r--src/test/codegen/enum-bounds-check-issue-13926.rs3
-rw-r--r--src/test/codegen/enum-bounds-check.rs3
-rw-r--r--src/test/codegen/enum-match.rs109
-rw-r--r--src/test/codegen/ffi-const.rs3
-rw-r--r--src/test/codegen/ffi-pure.rs3
-rw-r--r--src/test/codegen/issue-103285-ptr-addr-overflow-check.rs16
-rw-r--r--src/test/codegen/issue-37945.rs4
-rw-r--r--src/test/codegen/issue-81408-dllimport-thinlto-windows.rs15
-rw-r--r--src/test/codegen/iter-repeat-n-trivial-drop.rs56
-rw-r--r--src/test/codegen/match-optimized.rs60
-rw-r--r--src/test/codegen/match-unoptimized.rs23
-rw-r--r--src/test/codegen/match.rs29
-rw-r--r--src/test/codegen/mem-replace-direct-memcpy.rs4
-rw-r--r--src/test/codegen/naked-nocoverage.rs19
-rw-r--r--src/test/codegen/option-nonzero-eq.rs34
-rw-r--r--src/test/codegen/panic-abort-windows.rs15
-rw-r--r--src/test/codegen/repeat-trusted-len.rs7
-rw-r--r--src/test/codegen/slice-iter-len-eq-zero.rs2
-rw-r--r--src/test/codegen/static-relocation-model-msvc.rs26
-rw-r--r--src/test/codegen/unchecked_shifts.rs66
27 files changed, 482 insertions, 84 deletions
diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs
index b4fda5f8c..9061d7432 100644
--- a/src/test/codegen/abi-efiapi.rs
+++ b/src/test/codegen/abi-efiapi.rs
@@ -27,7 +27,7 @@ trait Copy { }
//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//aarch64: define dso_local void @has_efiapi
-//arm: define dso_local void @has_efiapi
+//arm: define dso_local arm_aapcscc void @has_efiapi
//riscv: define dso_local void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
diff --git a/src/test/codegen/async-fn-debug-awaitee-field.rs b/src/test/codegen/async-fn-debug-awaitee-field.rs
index 909cd0062..bc2686158 100644
--- a/src/test/codegen/async-fn-debug-awaitee-field.rs
+++ b/src/test/codegen/async-fn-debug-awaitee-field.rs
@@ -11,12 +11,14 @@ async fn async_fn_test() {
foo().await;
}
-// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
+// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]],
// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
+// NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test",
// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
-// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>",
-// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >",
+// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
+// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
+// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
fn main() {
let _fn = async_fn_test();
diff --git a/src/test/codegen/auxiliary/extern_decl.rs b/src/test/codegen/auxiliary/extern_decl.rs
new file mode 100644
index 000000000..edc483518
--- /dev/null
+++ b/src/test/codegen/auxiliary/extern_decl.rs
@@ -0,0 +1,11 @@
+// Auxiliary crate that exports a function and static. Both always
+// evaluate to `71`. We force mutability on the static to prevent
+// it from being inlined as constant.
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn extern_fn() -> u8 { unsafe { extern_static } }
+
+#[no_mangle]
+pub static mut extern_static: u8 = 71;
diff --git a/src/test/codegen/auxiliary/static_dllimport_aux.rs b/src/test/codegen/auxiliary/static_dllimport_aux.rs
new file mode 100644
index 000000000..afb0dc42f
--- /dev/null
+++ b/src/test/codegen/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/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs
index a038dfe76..cbbcfad3e 100644
--- a/src/test/codegen/avr/avr-func-addrspace.rs
+++ b/src/test/codegen/avr/avr-func-addrspace.rs
@@ -19,6 +19,8 @@ pub trait Sized { }
pub trait Copy { }
#[lang = "receiver"]
pub trait Receiver { }
+#[lang = "tuple_trait"]
+pub trait Tuple { }
pub struct Result<T, E> { _a: T, _b: E }
@@ -29,7 +31,7 @@ impl Copy for &usize {}
pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
#[lang = "fn_once"]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
@@ -37,24 +39,16 @@ pub trait FnOnce<Args> {
}
#[lang = "fn_mut"]
-pub trait FnMut<Args> : FnOnce<Args> {
+pub trait FnMut<Args: Tuple> : FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
#[lang = "fn"]
-pub trait Fn<Args>: FnOnce<Args> {
+pub trait Fn<Args: Tuple>: FnOnce<Args> {
/// Performs the call operation.
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
-impl<'a, A, R> FnOnce<A> for &'a fn(A) -> R {
- type Output = R;
-
- extern "rust-call" fn call_once(self, args: A) -> R {
- (*self)(args)
- }
-}
-
pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
pub static mut STORAGE_BAR: u32 = 12;
diff --git a/src/test/codegen/dllimports/main.rs b/src/test/codegen/dllimports/main.rs
index bb3134e81..ab599992f 100644
--- a/src/test/codegen/dllimports/main.rs
+++ b/src/test/codegen/dllimports/main.rs
@@ -1,17 +1,6 @@
// This test is for *-windows-msvc only.
-// ignore-android
-// ignore-dragonfly
-// ignore-emscripten
-// ignore-freebsd
+// only-windows
// ignore-gnu
-// ignore-haiku
-// ignore-ios
-// ignore-linux
-// ignore-macos
-// ignore-netbsd
-// ignore-openbsd
-// ignore-solaris
-// ignore-sgx no dynamic linking
// aux-build:dummy.rs
// aux-build:wrapper.rs
diff --git a/src/test/codegen/enum-bounds-check-derived-idx.rs b/src/test/codegen/enum-bounds-check-derived-idx.rs
index fe02aeb5f..aa66c2ed0 100644
--- a/src/test/codegen/enum-bounds-check-derived-idx.rs
+++ b/src/test/codegen/enum-bounds-check-derived-idx.rs
@@ -12,15 +12,13 @@ pub enum Bar {
// CHECK-LABEL: @lookup_inc
#[no_mangle]
pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
- // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
- // CHECK: panic_bounds_check
+ // CHECK-NOT: panic_bounds_check
buf[f as usize + 1]
}
// CHECK-LABEL: @lookup_dec
#[no_mangle]
pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
- // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
- // CHECK: panic_bounds_check
+ // CHECK-NOT: panic_bounds_check
buf[f as usize - 1]
}
diff --git a/src/test/codegen/enum-bounds-check-issue-13926.rs b/src/test/codegen/enum-bounds-check-issue-13926.rs
index 1aec41d54..b26945bc5 100644
--- a/src/test/codegen/enum-bounds-check-issue-13926.rs
+++ b/src/test/codegen/enum-bounds-check-issue-13926.rs
@@ -13,7 +13,6 @@ pub enum Exception {
// CHECK-LABEL: @access
#[no_mangle]
pub fn access(array: &[usize; 12], exc: Exception) -> usize {
- // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
- // CHECK: panic_bounds_check
+ // CHECK-NOT: panic_bounds_check
array[(exc as u8 - 4) as usize]
}
diff --git a/src/test/codegen/enum-bounds-check.rs b/src/test/codegen/enum-bounds-check.rs
index f85c6817d..17322d591 100644
--- a/src/test/codegen/enum-bounds-check.rs
+++ b/src/test/codegen/enum-bounds-check.rs
@@ -21,7 +21,6 @@ pub enum Bar {
// CHECK-LABEL: @lookup_unmodified
#[no_mangle]
pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 {
- // FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
- // CHECK: panic_bounds_check
+ // CHECK-NOT: panic_bounds_check
buf[f as usize]
}
diff --git a/src/test/codegen/enum-match.rs b/src/test/codegen/enum-match.rs
new file mode 100644
index 000000000..44f1b408d
--- /dev/null
+++ b/src/test/codegen/enum-match.rs
@@ -0,0 +1,109 @@
+// compile-flags: -Copt-level=1
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// Check each of the 3 cases for `codegen_get_discr`.
+
+// Case 0: One tagged variant.
+pub enum Enum0 {
+ A(bool),
+ B,
+}
+
+// CHECK: define i8 @match0{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = icmp eq i8 %0, 2
+// CHECK-NEXT: %2 = and i8 %0, 1
+// CHECK-NEXT: %.0 = select i1 %1, i8 13, i8 %2
+#[no_mangle]
+pub fn match0(e: Enum0) -> u8 {
+ use Enum0::*;
+ match e {
+ A(b) => b as u8,
+ B => 13,
+ }
+}
+
+// Case 1: Niche values are on a boundary for `range`.
+pub enum Enum1 {
+ A(bool),
+ B,
+ C,
+}
+
+// CHECK: define i8 @match1{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
+// CHECK-NEXT: switch i8 %1, label {{.*}} [
+#[no_mangle]
+pub fn match1(e: Enum1) -> u8 {
+ use Enum1::*;
+ match e {
+ A(b) => b as u8,
+ B => 13,
+ C => 100,
+ }
+}
+
+// Case 2: Special cases don't apply.
+pub enum X {
+ _2=2, _3, _4, _5, _6, _7, _8, _9, _10, _11,
+ _12, _13, _14, _15, _16, _17, _18, _19, _20,
+ _21, _22, _23, _24, _25, _26, _27, _28, _29,
+ _30, _31, _32, _33, _34, _35, _36, _37, _38,
+ _39, _40, _41, _42, _43, _44, _45, _46, _47,
+ _48, _49, _50, _51, _52, _53, _54, _55, _56,
+ _57, _58, _59, _60, _61, _62, _63, _64, _65,
+ _66, _67, _68, _69, _70, _71, _72, _73, _74,
+ _75, _76, _77, _78, _79, _80, _81, _82, _83,
+ _84, _85, _86, _87, _88, _89, _90, _91, _92,
+ _93, _94, _95, _96, _97, _98, _99, _100, _101,
+ _102, _103, _104, _105, _106, _107, _108, _109,
+ _110, _111, _112, _113, _114, _115, _116, _117,
+ _118, _119, _120, _121, _122, _123, _124, _125,
+ _126, _127, _128, _129, _130, _131, _132, _133,
+ _134, _135, _136, _137, _138, _139, _140, _141,
+ _142, _143, _144, _145, _146, _147, _148, _149,
+ _150, _151, _152, _153, _154, _155, _156, _157,
+ _158, _159, _160, _161, _162, _163, _164, _165,
+ _166, _167, _168, _169, _170, _171, _172, _173,
+ _174, _175, _176, _177, _178, _179, _180, _181,
+ _182, _183, _184, _185, _186, _187, _188, _189,
+ _190, _191, _192, _193, _194, _195, _196, _197,
+ _198, _199, _200, _201, _202, _203, _204, _205,
+ _206, _207, _208, _209, _210, _211, _212, _213,
+ _214, _215, _216, _217, _218, _219, _220, _221,
+ _222, _223, _224, _225, _226, _227, _228, _229,
+ _230, _231, _232, _233, _234, _235, _236, _237,
+ _238, _239, _240, _241, _242, _243, _244, _245,
+ _246, _247, _248, _249, _250, _251, _252, _253,
+}
+
+pub enum Enum2 {
+ A(X),
+ B,
+ C,
+ D,
+ E,
+}
+
+// CHECK: define i8 @match2{{.*}}
+// CHECK-NEXT: start:
+// CHECK-NEXT: %1 = add i8 %0, 2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 4
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+// CHECK-NEXT: switch i64 %_2, label {{.*}} [
+#[no_mangle]
+pub fn match2(e: Enum2) -> u8 {
+ use Enum2::*;
+ match e {
+ A(b) => b as u8,
+ B => 13,
+ C => 100,
+ D => 200,
+ E => 250,
+ }
+}
diff --git a/src/test/codegen/ffi-const.rs b/src/test/codegen/ffi-const.rs
index d9cfa5429..937205034 100644
--- a/src/test/codegen/ffi-const.rs
+++ b/src/test/codegen/ffi-const.rs
@@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } }
extern "C" {
// CHECK-LABEL: declare{{.*}}void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
- // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} }
+ // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0.
+ // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} }
#[ffi_const] pub fn foo();
}
diff --git a/src/test/codegen/ffi-pure.rs b/src/test/codegen/ffi-pure.rs
index 5bdb2ee91..2ed735813 100644
--- a/src/test/codegen/ffi-pure.rs
+++ b/src/test/codegen/ffi-pure.rs
@@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } }
extern "C" {
// CHECK-LABEL: declare{{.*}}void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
- // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} }
+ // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0.
+ // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} }
#[ffi_pure] pub fn foo();
}
diff --git a/src/test/codegen/issue-103285-ptr-addr-overflow-check.rs b/src/test/codegen/issue-103285-ptr-addr-overflow-check.rs
new file mode 100644
index 000000000..a3499babe
--- /dev/null
+++ b/src/test/codegen/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/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs
index 12fa1e9e5..fe54375bb 100644
--- a/src/test/codegen/issue-37945.rs
+++ b/src/test/codegen/issue-37945.rs
@@ -15,7 +15,7 @@ use std::slice::Iter;
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.1, null
+// 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.
@@ -28,7 +28,7 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool {
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.1, null
+// 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.
diff --git a/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs b/src/test/codegen/issue-81408-dllimport-thinlto-windows.rs
new file mode 100644
index 000000000..0b6ab4f7e
--- /dev/null
+++ b/src/test/codegen/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/src/test/codegen/iter-repeat-n-trivial-drop.rs b/src/test/codegen/iter-repeat-n-trivial-drop.rs
new file mode 100644
index 000000000..20e1d9b4d
--- /dev/null
+++ b/src/test/codegen/iter-repeat-n-trivial-drop.rs
@@ -0,0 +1,56 @@
+// compile-flags: -O
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(iter_repeat_n)]
+
+#[derive(Clone)]
+pub struct NotCopy(u16);
+
+impl Drop for NotCopy {
+ fn drop(&mut self) {}
+}
+
+// For a type where `Drop::drop` doesn't do anything observable and a clone is the
+// same as a move, make sure that the extra case for the last item disappears.
+
+#[no_mangle]
+// CHECK-LABEL: @iter_repeat_n_next
+pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCopy> {
+ // CHECK-NEXT: start:
+ // CHECK-NOT: br
+ // CHECK: %[[COUNT:.+]] = load i64
+ // CHECK-NEXT: %[[COUNT_ZERO:.+]] = icmp eq i64 %[[COUNT]], 0
+ // CHECK-NEXT: br i1 %[[COUNT_ZERO]], label %[[EMPTY:.+]], label %[[NOT_EMPTY:.+]]
+
+ // CHECK: [[NOT_EMPTY]]:
+ // CHECK-NEXT: %[[DEC:.+]] = add i64 %[[COUNT]], -1
+ // CHECK-NEXT: store i64 %[[DEC]]
+ // CHECK-NOT: br
+ // CHECK: %[[VAL:.+]] = load i16
+ // CHECK-NEXT: br label %[[EMPTY]]
+
+ // CHECK: [[EMPTY]]:
+ // CHECK-NOT: br
+ // CHECK: phi i16 [ undef, %start ], [ %[[VAL]], %[[NOT_EMPTY]] ]
+ // CHECK-NOT: br
+ // CHECK: ret
+
+ it.next()
+}
+
+// And as a result, using the iterator can optimize without special cases for
+// the last iteration, like `memset`ing all the items in one call.
+
+#[no_mangle]
+// CHECK-LABEL: @vec_extend_via_iter_repeat_n
+pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
+ // CHECK: %[[ADDR:.+]] = tail call dereferenceable_or_null(1234) ptr @__rust_alloc(i64 1234, i64 1)
+ // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
+
+ let n = 1234_usize;
+ let mut v = Vec::with_capacity(n);
+ v.extend(std::iter::repeat_n(42_u8, n));
+ v
+}
diff --git a/src/test/codegen/match-optimized.rs b/src/test/codegen/match-optimized.rs
new file mode 100644
index 000000000..36402cc73
--- /dev/null
+++ b/src/test/codegen/match-optimized.rs
@@ -0,0 +1,60 @@
+// compile-flags: -C no-prepopulate-passes -O
+
+#![crate_type = "lib"]
+
+pub enum E {
+ A,
+ B,
+ C,
+}
+
+// CHECK-LABEL: @exhaustive_match
+#[no_mangle]
+pub fn exhaustive_match(e: E) -> u8 {
+// CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[C:[a-zA-Z0-9_]+]]
+// CHECK-NEXT: ]
+// CHECK: [[OTHERWISE]]:
+// CHECK-NEXT: unreachable
+//
+// CHECK: [[A]]:
+// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
+// CHECK: [[B]]:
+// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: br label %[[EXIT]]
+// CHECK: [[C]]:
+// CHECK-NEXT: store i8 2, {{i8\*|ptr}} %1, align 1
+// CHECK-NEXT: br label %[[EXIT]]
+ match e {
+ E::A => 0,
+ E::B => 1,
+ E::C => 2,
+ }
+}
+
+#[repr(u16)]
+pub enum E2 {
+ A = 13,
+ B = 42,
+}
+
+// For optimized code we produce a switch with an unreachable target as the `otherwise` so LLVM
+// knows the possible values. Compare with `src/test/codegen/match-unoptimized.rs`.
+
+// CHECK-LABEL: @exhaustive_match_2
+#[no_mangle]
+pub fn exhaustive_match_2(e: E2) -> u8 {
+ // CHECK: switch i16 %{{.+}}, label %[[UNREACH:.+]] [
+ // CHECK-NEXT: i16 13,
+ // CHECK-NEXT: i16 42,
+ // CHECK-NEXT: ]
+ // CHECK: [[UNREACH]]:
+ // CHECK-NEXT: unreachable
+ match e {
+ E2::A => 0,
+ E2::B => 1,
+ }
+}
diff --git a/src/test/codegen/match-unoptimized.rs b/src/test/codegen/match-unoptimized.rs
new file mode 100644
index 000000000..be40b29e3
--- /dev/null
+++ b/src/test/codegen/match-unoptimized.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+#[repr(u16)]
+pub enum E2 {
+ A = 13,
+ B = 42,
+}
+
+// For unoptimized code we produce a `br` instead of a `switch`. Compare with
+// `src/test/codegen/match-optimized.rs`
+
+// CHECK-LABEL: @exhaustive_match_2
+#[no_mangle]
+pub fn exhaustive_match_2(e: E2) -> u8 {
+ // CHECK: %[[CMP:.+]] = icmp eq i16 %{{.+}}, 13
+ // CHECK-NEXT: br i1 %[[CMP:.+]],
+ match e {
+ E2::A => 0,
+ E2::B => 1,
+ }
+}
diff --git a/src/test/codegen/match.rs b/src/test/codegen/match.rs
deleted file mode 100644
index b203641fd..000000000
--- a/src/test/codegen/match.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "lib"]
-
-pub enum E {
- A,
- B,
-}
-
-// CHECK-LABEL: @exhaustive_match
-#[no_mangle]
-pub fn exhaustive_match(e: E) -> u8 {
-// CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [
-// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]]
-// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]]
-// CHECK-NEXT: ]
-// CHECK: [[OTHERWISE]]:
-// CHECK-NEXT: unreachable
-// CHECK: [[A]]:
-// CHECK-NEXT: store i8 0, {{i8\*|ptr}} %1, align 1
-// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
-// CHECK: [[B]]:
-// CHECK-NEXT: store i8 1, {{i8\*|ptr}} %1, align 1
-// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
- match e {
- E::A => 0,
- E::B => 1,
- }
-}
diff --git a/src/test/codegen/mem-replace-direct-memcpy.rs b/src/test/codegen/mem-replace-direct-memcpy.rs
index 4318e926e..e8bbf0e1b 100644
--- a/src/test/codegen/mem-replace-direct-memcpy.rs
+++ b/src/test/codegen/mem-replace-direct-memcpy.rs
@@ -18,7 +18,7 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
// CHECK-NOT: call void @llvm.memcpy
// CHECK: ; core::mem::replace
// CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %dest, i{{.*}} 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
// CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %dest, {{i8\*|ptr}} align 1 %src{{.*}}, i{{.*}} 1, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
// CHECK-NOT: call void @llvm.memcpy
diff --git a/src/test/codegen/naked-nocoverage.rs b/src/test/codegen/naked-nocoverage.rs
new file mode 100644
index 000000000..91a6260bf
--- /dev/null
+++ b/src/test/codegen/naked-nocoverage.rs
@@ -0,0 +1,19 @@
+// Checks that naked functions are not instrumented by -Cinstrument-coverage.
+// Regression test for issue #105170.
+//
+// needs-asm-support
+// needs-profiler-support
+// compile-flags: -Cinstrument-coverage
+#![crate_type = "lib"]
+#![feature(naked_functions)]
+use std::arch::asm;
+
+#[naked]
+#[no_mangle]
+pub unsafe extern "C" fn f() {
+ // CHECK: define void @f()
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: call void asm
+ // CHECK-NEXT: unreachable
+ asm!("", options(noreturn));
+}
diff --git a/src/test/codegen/option-nonzero-eq.rs b/src/test/codegen/option-nonzero-eq.rs
new file mode 100644
index 000000000..598dcc19b
--- /dev/null
+++ b/src/test/codegen/option-nonzero-eq.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -Zmerge-functions=disabled
+
+#![crate_type = "lib"]
+
+extern crate core;
+use core::num::{NonZeroU32, NonZeroI64};
+use core::ptr::NonNull;
+
+// CHECK-lABEL: @non_zero_eq
+#[no_mangle]
+pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
+ // CHECK: start:
+ // CHECK-NEXT: icmp eq i32
+ // CHECK-NEXT: ret i1
+ l == r
+}
+
+// CHECK-lABEL: @non_zero_signed_eq
+#[no_mangle]
+pub fn non_zero_signed_eq(l: Option<NonZeroI64>, r: Option<NonZeroI64>) -> bool {
+ // CHECK: start:
+ // CHECK-NEXT: icmp eq i64
+ // CHECK-NEXT: ret i1
+ l == r
+}
+
+// CHECK-lABEL: @non_null_eq
+#[no_mangle]
+pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
+ // CHECK: start:
+ // CHECK-NEXT: icmp eq {{(i8\*|ptr)}}
+ // CHECK-NEXT: ret i1
+ l == r
+}
diff --git a/src/test/codegen/panic-abort-windows.rs b/src/test/codegen/panic-abort-windows.rs
index 9ee4bfc47..2ee29762d 100644
--- a/src/test/codegen/panic-abort-windows.rs
+++ b/src/test/codegen/panic-abort-windows.rs
@@ -1,16 +1,5 @@
-// This test is for *-windows-msvc only.
-// ignore-android
-// ignore-dragonfly
-// ignore-emscripten
-// ignore-freebsd
-// ignore-haiku
-// ignore-ios
-// ignore-linux
-// ignore-macos
-// ignore-netbsd
-// ignore-openbsd
-// ignore-solaris
-// ignore-sgx
+// This test is for *-windows only.
+// only-windows
// compile-flags: -C no-prepopulate-passes -C panic=abort -O
diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs
index 7aebd3ec7..87c8fe135 100644
--- a/src/test/codegen/repeat-trusted-len.rs
+++ b/src/test/codegen/repeat-trusted-len.rs
@@ -11,3 +11,10 @@ pub fn repeat_take_collect() -> Vec<u8> {
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false)
iter::repeat(42).take(100000).collect()
}
+
+// CHECK-LABEL: @repeat_with_take_collect
+#[no_mangle]
+pub fn repeat_with_take_collect() -> Vec<u8> {
+// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}align 1{{.*}} %{{[0-9]+}}, i8 13, i{{[0-9]+}} 12345, i1 false)
+ iter::repeat_with(|| 13).take(12345).collect()
+}
diff --git a/src/test/codegen/slice-iter-len-eq-zero.rs b/src/test/codegen/slice-iter-len-eq-zero.rs
index 112402825..894b0ec3d 100644
--- a/src/test/codegen/slice-iter-len-eq-zero.rs
+++ b/src/test/codegen/slice-iter-len-eq-zero.rs
@@ -9,7 +9,7 @@ type Demo = [u8; 3];
#[no_mangle]
pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
// CHECK-NOT: sub
- // CHECK: %2 = icmp eq {{i8\*|ptr}} %1, %0
+ // CHECK: %2 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}}
// CHECK: ret i1 %2
y.len() == 0
}
diff --git a/src/test/codegen/static-relocation-model-msvc.rs b/src/test/codegen/static-relocation-model-msvc.rs
new file mode 100644
index 000000000..b2afc7deb
--- /dev/null
+++ b/src/test/codegen/static-relocation-model-msvc.rs
@@ -0,0 +1,26 @@
+// Verify linkage of external symbols in the static relocation model on MSVC.
+//
+// compile-flags: -O -C relocation-model=static
+// aux-build: extern_decl.rs
+// only-x86_64-pc-windows-msvc
+
+#![crate_type = "rlib"]
+
+extern crate extern_decl;
+
+// The `extern_decl` definitions are imported from a statically linked rust
+// crate, thus they are expected to be marked `dso_local` without `dllimport`.
+//
+// The `access_extern()` symbol is from this compilation unit, thus we expect
+// it to be marked `dso_local` as well, given the static relocation model.
+//
+// CHECK: @extern_static = external dso_local local_unnamed_addr global i8
+// CHECK: define dso_local i8 @access_extern() {{.*}}
+// CHECK: declare dso_local i8 @extern_fn() {{.*}}
+
+#[no_mangle]
+pub fn access_extern() -> u8 {
+ unsafe {
+ extern_decl::extern_fn() + extern_decl::extern_static
+ }
+}
diff --git a/src/test/codegen/unchecked_shifts.rs b/src/test/codegen/unchecked_shifts.rs
new file mode 100644
index 000000000..60d0cb09a
--- /dev/null
+++ b/src/test/codegen/unchecked_shifts.rs
@@ -0,0 +1,66 @@
+// compile-flags: -O
+// min-llvm-version: 15.0 (LLVM 13 in CI does this differently from submodule LLVM)
+// ignore-debug (because unchecked is checked in debug)
+
+#![crate_type = "lib"]
+#![feature(unchecked_math)]
+
+// CHECK-LABEL: @unchecked_shl_unsigned_same
+#[no_mangle]
+pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 {
+ // CHECK-NOT: and i32
+ // CHECK: shl i32 %a, %b
+ // CHECK-NOT: and i32
+ a.unchecked_shl(b)
+}
+
+// CHECK-LABEL: @unchecked_shl_unsigned_smaller
+#[no_mangle]
+pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
+ // This uses -DAG to avoid failing on irrelevant reorderings,
+ // like emitting the truncation earlier.
+
+ // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 65536
+ // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
+ // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
+ // CHECK-DAG: shl i16 %a, %[[TRUNC]]
+ a.unchecked_shl(b)
+}
+
+// CHECK-LABEL: @unchecked_shl_unsigned_bigger
+#[no_mangle]
+pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
+ // CHECK: %[[EXT:.+]] = zext i32 %b to i64
+ // CHECK: shl i64 %a, %[[EXT]]
+ a.unchecked_shl(b)
+}
+
+// CHECK-LABEL: @unchecked_shr_signed_same
+#[no_mangle]
+pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 {
+ // CHECK-NOT: and i32
+ // CHECK: ashr i32 %a, %b
+ // CHECK-NOT: and i32
+ a.unchecked_shr(b)
+}
+
+// CHECK-LABEL: @unchecked_shr_signed_smaller
+#[no_mangle]
+pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
+ // This uses -DAG to avoid failing on irrelevant reorderings,
+ // like emitting the truncation earlier.
+
+ // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 32768
+ // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
+ // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
+ // CHECK-DAG: ashr i16 %a, %[[TRUNC]]
+ a.unchecked_shr(b)
+}
+
+// CHECK-LABEL: @unchecked_shr_signed_bigger
+#[no_mangle]
+pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
+ // CHECK: %[[EXT:.+]] = zext i32 %b to i64
+ // CHECK: ashr i64 %a, %[[EXT]]
+ a.unchecked_shr(b)
+}