summaryrefslogtreecommitdiffstats
path: root/tests/codegen
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
commit631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch)
treea1b87c8f8cad01cf18f7c5f57a08f102771ed303 /tests/codegen
parentAdding debian version 1.69.0+dfsg1-1. (diff)
downloadrustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz
rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/abi-main-signature-16bit-c-int.rs1
-rw-r--r--tests/codegen/adjustments.rs2
-rw-r--r--tests/codegen/array-map.rs6
-rw-r--r--tests/codegen/comparison-operators-2-tuple.rs121
-rw-r--r--tests/codegen/consts.rs2
-rw-r--r--tests/codegen/debug-limited.rs27
-rw-r--r--tests/codegen/debug-line-directives-only.rs27
-rw-r--r--tests/codegen/debug-line-tables-only.rs27
-rw-r--r--tests/codegen/enum-match.rs7
-rw-r--r--tests/codegen/fewer-names.rs4
-rw-r--r--tests/codegen/global_asm.rs27
-rw-r--r--tests/codegen/global_asm_include.rs27
-rw-r--r--tests/codegen/global_asm_x2.rs27
-rw-r--r--tests/codegen/inherit_overflow.rs2
-rw-r--r--tests/codegen/inline-function-args-debug-info.rs20
-rw-r--r--tests/codegen/intrinsics/transmute-x64.rs35
-rw-r--r--tests/codegen/intrinsics/transmute.rs431
-rw-r--r--tests/codegen/issues/auxiliary/static_dllimport_aux.rs (renamed from tests/codegen/auxiliary/static_dllimport_aux.rs)0
-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.rs (renamed from tests/codegen/issue-103285-ptr-addr-overflow-check.rs)0
-rw-r--r--tests/codegen/issues/issue-103327.rs18
-rw-r--r--tests/codegen/issues/issue-103840.rs (renamed from tests/codegen/issue-103840.rs)0
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs (renamed from tests/codegen/issue-105386-ub-in-debuginfo.rs)0
-rw-r--r--tests/codegen/issues/issue-106369.rs15
-rw-r--r--tests/codegen/issues/issue-13018.rs (renamed from tests/codegen/issue-13018.rs)0
-rw-r--r--tests/codegen/issues/issue-15953.rs (renamed from tests/codegen/issue-15953.rs)0
-rw-r--r--tests/codegen/issues/issue-27130.rs (renamed from tests/codegen/issue-27130.rs)0
-rw-r--r--tests/codegen/issues/issue-32031.rs (renamed from tests/codegen/issue-32031.rs)0
-rw-r--r--tests/codegen/issues/issue-32364.rs (renamed from tests/codegen/issue-32364.rs)0
-rw-r--r--tests/codegen/issues/issue-34634.rs (renamed from tests/codegen/issue-34634.rs)0
-rw-r--r--tests/codegen/issues/issue-34947-pow-i32.rs (renamed from tests/codegen/issue-34947-pow-i32.rs)0
-rw-r--r--tests/codegen/issues/issue-37945.rs (renamed from tests/codegen/issue-37945.rs)7
-rw-r--r--tests/codegen/issues/issue-44056-macos-tls-align.rs (renamed from tests/codegen/issue-44056-macos-tls-align.rs)0
-rw-r--r--tests/codegen/issues/issue-45222.rs (renamed from tests/codegen/issue-45222.rs)0
-rw-r--r--tests/codegen/issues/issue-45466.rs (renamed from tests/codegen/issue-45466.rs)0
-rw-r--r--tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs (renamed from tests/codegen/issue-45964-bounds-check-slice-pos.rs)0
-rw-r--r--tests/codegen/issues/issue-47278.rs (renamed from tests/codegen/issue-47278.rs)0
-rw-r--r--tests/codegen/issues/issue-47442.rs (renamed from tests/codegen/issue-47442.rs)0
-rw-r--r--tests/codegen/issues/issue-56267-2.rs (renamed from tests/codegen/issue-56267-2.rs)0
-rw-r--r--tests/codegen/issues/issue-56267.rs (renamed from tests/codegen/issue-56267.rs)0
-rw-r--r--tests/codegen/issues/issue-56927.rs (renamed from tests/codegen/issue-56927.rs)0
-rw-r--r--tests/codegen/issues/issue-58881.rs (renamed from tests/codegen/issue-58881.rs)0
-rw-r--r--tests/codegen/issues/issue-59352.rs (renamed from tests/codegen/issue-59352.rs)0
-rw-r--r--tests/codegen/issues/issue-69101-bounds-check.rs (renamed from tests/codegen/issue-69101-bounds-check.rs)0
-rw-r--r--tests/codegen/issues/issue-73031.rs (renamed from tests/codegen/issue-73031.rs)0
-rw-r--r--tests/codegen/issues/issue-73258.rs38
-rw-r--r--tests/codegen/issues/issue-73338-effecient-cmp.rs (renamed from tests/codegen/issue-73338-effecient-cmp.rs)0
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs (renamed from tests/codegen/issue-73396-bounds-check-after-position.rs)0
-rw-r--r--tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs (renamed from tests/codegen/issue-73827-bounds-check-index-in-subexpr.rs)0
-rw-r--r--tests/codegen/issues/issue-75525-bounds-checks.rs (renamed from tests/codegen/issue-75525-bounds-checks.rs)0
-rw-r--r--tests/codegen/issues/issue-75546.rs (renamed from tests/codegen/issue-75546.rs)0
-rw-r--r--tests/codegen/issues/issue-75659.rs (renamed from tests/codegen/issue-75659.rs)0
-rw-r--r--tests/codegen/issues/issue-75978.rs19
-rw-r--r--tests/codegen/issues/issue-77812.rs (renamed from tests/codegen/issue-77812.rs)0
-rw-r--r--tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs (renamed from tests/codegen/issue-81408-dllimport-thinlto-windows.rs)0
-rw-r--r--tests/codegen/issues/issue-84268.rs (renamed from tests/codegen/issue-84268.rs)0
-rw-r--r--tests/codegen/issues/issue-85872-multiple-reverse.rs (renamed from tests/codegen/issue-85872-multiple-reverse.rs)0
-rw-r--r--tests/codegen/issues/issue-86106.rs (renamed from tests/codegen/issue-86106.rs)0
-rw-r--r--tests/codegen/issues/issue-96274.rs (renamed from tests/codegen/issue-96274.rs)0
-rw-r--r--tests/codegen/issues/issue-96497-slice-size-nowrap.rs (renamed from tests/codegen/issue-96497-slice-size-nowrap.rs)0
-rw-r--r--tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs (renamed from tests/codegen/issue-98156-const-arg-temp-lifetime.rs)0
-rw-r--r--tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs (renamed from tests/codegen/issue-98294-get-mut-copy-from-slice-opt.rs)0
-rw-r--r--tests/codegen/issues/issue-99960.rs15
-rw-r--r--tests/codegen/mem-replace-big-type.rs36
-rw-r--r--tests/codegen/mem-replace-direct-memcpy.rs21
-rw-r--r--tests/codegen/optimize-attr-1.rs3
-rw-r--r--tests/codegen/option-as-slice.rs18
-rw-r--r--tests/codegen/ptr-read-metadata.rs96
-rw-r--r--tests/codegen/remap_path_prefix/main.rs2
-rw-r--r--tests/codegen/repr-transparent-aggregates-2.rs1
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs51
-rw-r--r--tests/codegen/simd-wide-sum.rs2
-rw-r--r--tests/codegen/slice-indexing.rs35
-rw-r--r--tests/codegen/transmute-scalar.rs65
-rw-r--r--tests/codegen/var-names.rs4
-rw-r--r--tests/codegen/vec-as-ptr.rs19
-rw-r--r--tests/codegen/vec-in-place.rs42
-rw-r--r--tests/codegen/vec-shrink-panik.rs23
-rw-r--r--tests/codegen/virtual-function-elimination.rs5
82 files changed, 1220 insertions, 174 deletions
diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs
index 4ed491dfb..3548cc06a 100644
--- a/tests/codegen/abi-main-signature-16bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-16bit-c-int.rs
@@ -17,7 +17,6 @@
// ignore-wasm32
// ignore-x86
// ignore-x86_64
-// ignore-xcore
fn main() {
}
diff --git a/tests/codegen/adjustments.rs b/tests/codegen/adjustments.rs
index 6d2247517..b53a68a55 100644
--- a/tests/codegen/adjustments.rs
+++ b/tests/codegen/adjustments.rs
@@ -13,7 +13,7 @@ pub fn helper(_: usize) {
pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
// We used to generate an extra alloca and memcpy for the block's trailing expression value, so
// check that we copy directly to the return value slot
-// CHECK: %0 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } undef, {{\[0 x i8\]\*|ptr}} %x.0, 0
+// CHECK: %0 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } poison, {{\[0 x i8\]\*|ptr}} %x.0, 0
// CHECK: %1 = insertvalue { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %0, [[USIZE]] %x.1, 1
// CHECK: ret { {{\[0 x i8\]\*|ptr}}, [[USIZE]] } %1
{ x }
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
index 9298e89e3..7b8ab2c79 100644
--- a/tests/codegen/array-map.rs
+++ b/tests/codegen/array-map.rs
@@ -38,10 +38,10 @@ pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
//
// CHECK-LABEL: @long_integer_map
#[no_mangle]
-pub fn long_integer_map(x: [u32; 64]) -> [u32; 64] {
+pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] {
// CHECK: start:
- // CHECK-NEXT: alloca [64 x i32]
- // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 64]>"
+ // CHECK-NEXT: alloca [512 x i32]
+ // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 512]>"
// CHECK-NOT: alloca
// CHECK: mul <{{[0-9]+}} x i32>
// CHECK: add <{{[0-9]+}} x i32>
diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs
new file mode 100644
index 000000000..a9d25e3b5
--- /dev/null
+++ b/tests/codegen/comparison-operators-2-tuple.rs
@@ -0,0 +1,121 @@
+// compile-flags: -C opt-level=1 -Z merge-functions=disabled
+// min-llvm-version: 15.0
+// only-x86_64
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+type TwoTuple = (i16, u16);
+
+//
+// The operators are all overridden directly, so should optimize easily.
+//
+// Yes, the `s[lg]t` is correct for the `[lg]e` version because it's only used
+// in the side of the select where we know the values are *not* equal.
+//
+
+// CHECK-LABEL: @check_lt_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_lt_direct(a: TwoTuple, b: TwoTuple) -> bool {
+ // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
+ // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // CHECK: ret i1 %[[R]]
+ a < b
+}
+
+// CHECK-LABEL: @check_le_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_le_direct(a: TwoTuple, b: TwoTuple) -> bool {
+ // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
+ // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // CHECK: ret i1 %[[R]]
+ a <= b
+}
+
+// CHECK-LABEL: @check_gt_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_gt_direct(a: TwoTuple, b: TwoTuple) -> bool {
+ // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
+ // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // CHECK: ret i1 %[[R]]
+ a > b
+}
+
+// CHECK-LABEL: @check_ge_direct
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_ge_direct(a: TwoTuple, b: TwoTuple) -> bool {
+ // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
+ // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // CHECK: ret i1 %[[R]]
+ a >= b
+}
+
+//
+// These ones are harder, since there are more intermediate values to remove.
+//
+// `<` seems to be getting lucky right now, so test that doesn't regress.
+//
+// The others, however, aren't managing to optimize away the extra `select`s yet.
+// See <https://github.com/rust-lang/rust/issues/106107> for more about this.
+//
+
+// CHECK-LABEL: @check_lt_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_lt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+ // CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
+ // CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
+ // CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // CHECK: ret i1 %[[R]]
+ Ord::cmp(&a, &b).is_lt()
+}
+
+// CHECK-LABEL: @check_le_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_le_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+ // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sle i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
+ // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // FIXME-CHECK: ret i1 %[[R]]
+ Ord::cmp(&a, &b).is_le()
+}
+
+// CHECK-LABEL: @check_gt_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_gt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+ // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
+ // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // FIXME-CHECK: ret i1 %[[R]]
+ Ord::cmp(&a, &b).is_gt()
+}
+
+// CHECK-LABEL: @check_ge_via_cmp
+// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
+#[no_mangle]
+pub fn check_ge_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
+ // FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sge i16 %[[A0]], %[[B0]]
+ // FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
+ // FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
+ // FIXME-CHECK: ret i1 %[[R]]
+ Ord::cmp(&a, &b).is_ge()
+}
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index dd22fd0f7..fc2badc41 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -9,7 +9,7 @@
// CHECK: @STATIC = {{.*}}, align 4
// This checks the constants from inline_enum_const
-// CHECK: @alloc_76bfe2f13a3e3b01074971d122eac57e = {{.*}}, align 2
+// CHECK: @alloc_af1f8e8e6f4b341431a1d405e652df2d = {{.*}}, align 2
// This checks the constants from {low,high}_align_const, they share the same
// constant, but the alignment differs, so the higher one should be used
diff --git a/tests/codegen/debug-limited.rs b/tests/codegen/debug-limited.rs
new file mode 100644
index 000000000..48d676887
--- /dev/null
+++ b/tests/codegen/debug-limited.rs
@@ -0,0 +1,27 @@
+// Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info.
+//
+// compile-flags: -C debuginfo=limited
+
+#[repr(C)]
+struct StructType {
+ a: i64,
+ b: i32,
+}
+
+extern "C" {
+ fn creator() -> *mut StructType;
+ fn save(p: *const StructType);
+}
+
+fn main() {
+ unsafe {
+ let value: &mut StructType = &mut *creator();
+ value.a = 7;
+ save(value as *const StructType)
+ }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: FullDebug
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/debug-line-directives-only.rs b/tests/codegen/debug-line-directives-only.rs
new file mode 100644
index 000000000..750bdd49d
--- /dev/null
+++ b/tests/codegen/debug-line-directives-only.rs
@@ -0,0 +1,27 @@
+// Verify that the only debuginfo generated are the line directives.
+//
+// compile-flags: -C debuginfo=line-directives-only
+
+#[repr(C)]
+struct StructType {
+ a: i64,
+ b: i32,
+}
+
+extern "C" {
+ fn creator() -> *mut StructType;
+ fn save(p: *const StructType);
+}
+
+fn main() {
+ unsafe {
+ let value: &mut StructType = &mut *creator();
+ value.a = 7;
+ save(value as *const StructType)
+ }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: DebugDirectivesOnly
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/debug-line-tables-only.rs b/tests/codegen/debug-line-tables-only.rs
new file mode 100644
index 000000000..3ed165a6f
--- /dev/null
+++ b/tests/codegen/debug-line-tables-only.rs
@@ -0,0 +1,27 @@
+// Verify that the only debuginfo generated are the line tables.
+//
+// compile-flags: -C debuginfo=line-tables-only
+
+#[repr(C)]
+struct StructType {
+ a: i64,
+ b: i32,
+}
+
+extern "C" {
+ fn creator() -> *mut StructType;
+ fn save(p: *const StructType);
+}
+
+fn main() {
+ unsafe {
+ let value: &mut StructType = &mut *creator();
+ value.a = 7;
+ save(value as *const StructType)
+ }
+}
+
+// CHECK: !DICompileUnit
+// CHECK: emissionKind: LineTablesOnly
+// CHECK: !DILocation
+// CHECK-NOT: !DIBasicType
diff --git a/tests/codegen/enum-match.rs b/tests/codegen/enum-match.rs
index 5f8063a27..36c6be190 100644
--- a/tests/codegen/enum-match.rs
+++ b/tests/codegen/enum-match.rs
@@ -34,8 +34,11 @@ pub enum Enum1 {
// CHECK: define noundef i8 @match1{{.*}}
// CHECK-NEXT: start:
-// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
-// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
+// CHECK-NEXT: %1 = add i8 %0, -2
+// CHECK-NEXT: %2 = zext i8 %1 to i64
+// CHECK-NEXT: %3 = icmp ult i8 %1, 2
+// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
+// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
#[no_mangle]
pub fn match1(e: Enum1) -> u8 {
use Enum1::*;
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
index ac8cba06b..7f383a5c1 100644
--- a/tests/codegen/fewer-names.rs
+++ b/tests/codegen/fewer-names.rs
@@ -13,8 +13,8 @@ pub fn sum(x: u32, y: u32) -> u32 {
// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
// NO-NEXT: start:
-// NO-NEXT: %z = add i32 %y, %x
-// NO-NEXT: ret i32 %z
+// NO-NEXT: %0 = add i32 %y, %x
+// NO-NEXT: ret i32 %0
let z = x + y;
z
}
diff --git a/tests/codegen/global_asm.rs b/tests/codegen/global_asm.rs
index fab84868f..9912b1e75 100644
--- a/tests/codegen/global_asm.rs
+++ b/tests/codegen/global_asm.rs
@@ -1,39 +1,20 @@
// ignore-aarch64
-// ignore-aarch64_be
// ignore-arm
-// ignore-armeb
// ignore-avr
-// ignore-bpfel
-// ignore-bpfeb
+// ignore-bpf
+// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
-// ignore-powerpc64le
// ignore-powerpc
-// ignore-r600
-// ignore-amdgcn
// ignore-sparc
-// ignore-sparcv9
-// ignore-sparcel
+// ignore-sparc64
// ignore-s390x
-// ignore-tce
// ignore-thumb
-// ignore-thumbeb
-// ignore-xcore
-// ignore-nvptx
// ignore-nvptx64
-// ignore-le32
-// ignore-le64
-// ignore-amdil
-// ignore-amdil64
-// ignore-hsail
-// ignore-hsail64
-// ignore-spir
-// ignore-spir64
-// ignore-kalimba
-// ignore-shave
+// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
diff --git a/tests/codegen/global_asm_include.rs b/tests/codegen/global_asm_include.rs
index 02ee91645..b68c5ad3b 100644
--- a/tests/codegen/global_asm_include.rs
+++ b/tests/codegen/global_asm_include.rs
@@ -1,39 +1,20 @@
// ignore-aarch64
-// ignore-aarch64_be
// ignore-arm
-// ignore-armeb
// ignore-avr
-// ignore-bpfel
-// ignore-bpfeb
+// ignore-bpf
+// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
-// ignore-powerpc64le
// ignore-powerpc
-// ignore-r600
-// ignore-amdgcn
// ignore-sparc
-// ignore-sparcv9
-// ignore-sparcel
+// ignore-sparc64
// ignore-s390x
-// ignore-tce
// ignore-thumb
-// ignore-thumbeb
-// ignore-xcore
-// ignore-nvptx
// ignore-nvptx64
-// ignore-le32
-// ignore-le64
-// ignore-amdil
-// ignore-amdil64
-// ignore-hsail
-// ignore-hsail64
-// ignore-spir
-// ignore-spir64
-// ignore-kalimba
-// ignore-shave
+// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
diff --git a/tests/codegen/global_asm_x2.rs b/tests/codegen/global_asm_x2.rs
index bdcf0ea84..d87e02bef 100644
--- a/tests/codegen/global_asm_x2.rs
+++ b/tests/codegen/global_asm_x2.rs
@@ -1,39 +1,20 @@
// ignore-aarch64
-// ignore-aarch64_be
// ignore-arm
-// ignore-armeb
// ignore-avr
-// ignore-bpfel
-// ignore-bpfeb
+// ignore-bpf
+// ignore-bpf
// ignore-hexagon
// ignore-mips
// ignore-mips64
// ignore-msp430
// ignore-powerpc64
-// ignore-powerpc64le
// ignore-powerpc
-// ignore-r600
-// ignore-amdgcn
// ignore-sparc
-// ignore-sparcv9
-// ignore-sparcel
+// ignore-sparc64
// ignore-s390x
-// ignore-tce
// ignore-thumb
-// ignore-thumbeb
-// ignore-xcore
-// ignore-nvptx
// ignore-nvptx64
-// ignore-le32
-// ignore-le64
-// ignore-amdil
-// ignore-amdil64
-// ignore-hsail
-// ignore-hsail64
-// ignore-spir
-// ignore-spir64
-// ignore-kalimba
-// ignore-shave
+// ignore-spirv
// ignore-wasm32
// ignore-wasm64
// ignore-emscripten
diff --git a/tests/codegen/inherit_overflow.rs b/tests/codegen/inherit_overflow.rs
index 0b0b890b2..39909d7ab 100644
--- a/tests/codegen/inherit_overflow.rs
+++ b/tests/codegen/inherit_overflow.rs
@@ -4,7 +4,7 @@
//[NOASSERT] compile-flags: -Coverflow-checks=off
// CHECK-LABEL: define{{.*}} @assertion
-// ASSERT: call void @_ZN4core9panicking5panic17h
+// ASSERT: call void @{{.*4core9panicking5panic}}
// NOASSERT: ret i8 0
#[no_mangle]
pub fn assertion() -> u8 {
diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs
new file mode 100644
index 000000000..e3d8caa49
--- /dev/null
+++ b/tests/codegen/inline-function-args-debug-info.rs
@@ -0,0 +1,20 @@
+// This test checks that debug information includes function argument indexes even if the function
+// gets inlined by MIR inlining. Without function argument indexes, `info args` in gdb won't show
+// arguments and their values for the current function.
+
+// compile-flags: -Zinline-mir=yes -Cdebuginfo=2 --edition=2021
+
+#![crate_type = "lib"]
+
+pub fn outer_function(x: usize, y: usize) -> usize {
+ inner_function(x, y) + 1
+}
+
+#[inline]
+fn inner_function(aaaa: usize, bbbb: usize) -> usize {
+ // CHECK: !DILocalVariable(name: "aaaa", arg: 1
+ // CHECK-SAME: line: 14
+ // CHECK: !DILocalVariable(name: "bbbb", arg: 2
+ // CHECK-SAME: line: 14
+ aaaa + bbbb
+}
diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs
new file mode 100644
index 000000000..99d258c62
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-x64.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O -C no-prepopulate-passes
+// only-x86_64 (it's using arch-specific types)
+// min-llvm-version: 15.0 # this test assumes `ptr`s
+
+#![crate_type = "lib"]
+
+use std::arch::x86_64::{__m128, __m128i, __m256i};
+use std::mem::transmute;
+
+// CHECK-LABEL: @check_sse_float_to_int(
+#[no_mangle]
+pub unsafe fn check_sse_float_to_int(x: __m128) -> __m128i {
+ // CHECK-NOT: alloca
+ // CHECK: %1 = load <4 x float>, ptr %x, align 16
+ // CHECK: store <4 x float> %1, ptr %0, align 16
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_sse_pair_to_avx(
+#[no_mangle]
+pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i {
+ // CHECK-NOT: alloca
+ // CHECK: %1 = load <4 x i64>, ptr %x, align 16
+ // CHECK: store <4 x i64> %1, ptr %0, align 32
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_sse_pair_from_avx(
+#[no_mangle]
+pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) {
+ // CHECK-NOT: alloca
+ // CHECK: %1 = load <4 x i64>, ptr %x, align 32
+ // CHECK: store <4 x i64> %1, ptr %0, align 16
+ transmute(x)
+}
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
new file mode 100644
index 000000000..57f901c67
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -0,0 +1,431 @@
+// compile-flags: -O -C no-prepopulate-passes
+// only-64bit (so I don't need to worry about usize)
+// min-llvm-version: 15.0 # this test assumes `ptr`s
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+#![feature(custom_mir)]
+#![feature(inline_const)]
+#![allow(unreachable_code)]
+
+use std::mem::{transmute, MaybeUninit};
+
+// Some of the cases here are statically rejected by `mem::transmute`, so
+// we need to generate custom MIR for those cases to get to codegen.
+use std::intrinsics::mir::*;
+
+enum Never {}
+
+#[repr(align(2))]
+pub struct BigNever(Never, u16, Never);
+
+#[repr(align(8))]
+pub struct Scalar64(i64);
+
+#[repr(C, align(4))]
+pub struct Aggregate64(u16, u8, i8, f32);
+
+#[repr(C)]
+pub struct Aggregate8(u8);
+
+// CHECK-LABEL: @check_bigger_size(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_bigger_size(x: u16) -> u32 {
+ // CHECK: call void @llvm.trap
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_smaller_size(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_smaller_size(x: u32) -> u16 {
+ // CHECK: call void @llvm.trap
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_smaller_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
+ // CHECK: call void @llvm.trap
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_bigger_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
+ // CHECK: call void @llvm.trap
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_to_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
+ // CHECK: call void @llvm.trap
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_from_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "initial")]
+pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
+ // CHECK: ret i16 poison
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_intermediate_passthrough(
+#[no_mangle]
+pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 {
+ // CHECK: start
+ // CHECK: %[[TMP:.+]] = add i32 1, %x
+ // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1
+ // CHECK: ret i32 %[[RET]]
+ unsafe {
+ transmute::<u32, i32>(1 + x) + 1
+ }
+}
+
+// CHECK-LABEL: @check_nop_pair(
+#[no_mangle]
+pub unsafe fn check_nop_pair(x: (u8, i8)) -> (i8, u8) {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = insertvalue { i8, i8 } poison, i8 %x.0, 0
+ // CHECK: %1 = insertvalue { i8, i8 } %0, i8 %x.1, 1
+ // CHECK: ret { i8, i8 } %1
+ unsafe {
+ transmute(x)
+ }
+}
+
+// CHECK-LABEL: @check_to_newtype(
+#[no_mangle]
+pub unsafe fn check_to_newtype(x: u64) -> Scalar64 {
+ // CHECK-NOT: alloca
+ // CHECK: ret i64 %x
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_newtype(
+#[no_mangle]
+pub unsafe fn check_from_newtype(x: Scalar64) -> u64 {
+ // CHECK-NOT: alloca
+ // CHECK: ret i64 %x
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_aggregate_to_bool(
+#[no_mangle]
+pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool {
+ // CHECK: %x = alloca %Aggregate8, align 1
+ // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1
+ // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1
+ // CHECK: ret i1 %[[BOOL]]
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_aggregate_from_bool(
+#[no_mangle]
+pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
+ // CHECK: %0 = alloca %Aggregate8, align 1
+ // CHECK: %[[BYTE:.+]] = zext i1 %x to i8
+ // CHECK: store i8 %[[BYTE]], ptr %0, align 1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_byte_to_bool(
+#[no_mangle]
+pub unsafe fn check_byte_to_bool(x: u8) -> bool {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = trunc i8 %x to i1
+ // CHECK: ret i1 %0
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_byte_from_bool(
+#[no_mangle]
+pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = zext i1 %x to i8
+ // CHECK: ret i8 %0
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_pair(
+#[no_mangle]
+pub unsafe fn check_to_pair(x: u64) -> Option<i32> {
+ // CHECK: %0 = alloca { i32, i32 }, align 4
+ // CHECK: store i64 %x, ptr %0, align 4
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_pair(
+#[no_mangle]
+pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
+ // The two arguments are of types that are only 4-aligned, but they're
+ // immediates so we can write using the destination alloca's alignment.
+ const { assert!(std::mem::align_of::<Option<i32>>() == 4) };
+
+ // CHECK: %0 = alloca i64, align 8
+ // CHECK: store i32 %x.0, ptr %1, align 8
+ // CHECK: store i32 %x.1, ptr %2, align 4
+ // CHECK: %3 = load i64, ptr %0, align 8
+ // CHECK: ret i64 %3
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_float(
+#[no_mangle]
+pub unsafe fn check_to_float(x: u32) -> f32 {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = bitcast i32 %x to float
+ // CHECK: ret float %0
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_float(
+#[no_mangle]
+pub unsafe fn check_from_float(x: f32) -> u32 {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = bitcast float %x to i32
+ // CHECK: ret i32 %0
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_bytes(
+#[no_mangle]
+pub unsafe fn check_to_bytes(x: u32) -> [u8; 4] {
+ // CHECK: %0 = alloca [4 x i8], align 1
+ // CHECK: store i32 %x, ptr %0, align 1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_bytes(
+#[no_mangle]
+pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 {
+ // CHECK: %x = alloca [4 x i8], align 1
+ // CHECK: %[[VAL:.+]] = load i32, ptr %x, align 1
+ // CHECK: ret i32 %[[VAL]]
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_aggregate(
+#[no_mangle]
+pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 {
+ // CHECK: %0 = alloca %Aggregate64, align 4
+ // CHECK: store i64 %x, ptr %0, align 4
+ // CHECK: %1 = load i64, ptr %0, align 4
+ // CHECK: ret i64 %1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_aggregate(
+#[no_mangle]
+pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 {
+ // CHECK: %x = alloca %Aggregate64, align 4
+ // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 4
+ // CHECK: ret i64 %[[VAL]]
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_less_aligned(
+#[no_mangle]
+pub unsafe fn check_long_array_less_aligned(x: [u64; 100]) -> [u16; 400] {
+ // CHECK-NEXT: start
+ // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %0, ptr align 8 %x, i64 800, i1 false)
+ // CHECK-NEXT: ret void
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_long_array_more_aligned(
+#[no_mangle]
+pub unsafe fn check_long_array_more_aligned(x: [u8; 100]) -> [u32; 25] {
+ // CHECK-NEXT: start
+ // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %0, ptr align 1 %x, i64 100, i1 false)
+ // CHECK-NEXT: ret void
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_with_bool(
+#[no_mangle]
+pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) {
+ // CHECK-NOT: alloca
+ // CHECK: trunc i8 %x.0 to i1
+ // CHECK: zext i1 %x.1 to i8
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_float_to_pointer(
+#[no_mangle]
+pub unsafe fn check_float_to_pointer(x: f64) -> *const () {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = bitcast double %x to i64
+ // CHECK: %1 = inttoptr i64 %0 to ptr
+ // CHECK: ret ptr %1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_float_from_pointer(
+#[no_mangle]
+pub unsafe fn check_float_from_pointer(x: *const ()) -> f64 {
+ // CHECK-NOT: alloca
+ // CHECK: %0 = ptrtoint ptr %x to i64
+ // CHECK: %1 = bitcast i64 %0 to double
+ // CHECK: ret double %1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_array_to_pair(
+#[no_mangle]
+pub unsafe fn check_array_to_pair(x: [u8; 16]) -> (i64, u64) {
+ // CHECK-NOT: alloca
+ // CHECK: %[[FST:.+]] = load i64, ptr %{{.+}}, align 1, !noundef !
+ // CHECK: %[[SND:.+]] = load i64, ptr %{{.+}}, align 1, !noundef !
+ // CHECK: %[[PAIR0:.+]] = insertvalue { i64, i64 } poison, i64 %[[FST]], 0
+ // CHECK: %[[PAIR01:.+]] = insertvalue { i64, i64 } %[[PAIR0]], i64 %[[SND]], 1
+ // CHECK: ret { i64, i64 } %[[PAIR01]]
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_to_array(
+#[no_mangle]
+pub unsafe fn check_pair_to_array(x: (i64, u64)) -> [u8; 16] {
+ // CHECK-NOT: alloca
+ // CHECK: store i64 %x.0, ptr %{{.+}}, align 1
+ // CHECK: store i64 %x.1, ptr %{{.+}}, align 1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_heterogeneous_integer_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_integer_pair(x: (i32, bool)) -> (bool, u32) {
+ // CHECK: store i32 %x.0
+ // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+ // CHECK: store i8 %[[WIDER]]
+
+ // CHECK: %[[BYTE:.+]] = load i8
+ // CHECK: trunc i8 %[[BYTE:.+]] to i1
+ // CHECK: load i32
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_heterogeneous_float_pair(
+#[no_mangle]
+pub unsafe fn check_heterogeneous_float_pair(x: (f64, f32)) -> (f32, f64) {
+ // CHECK: store double %x.0
+ // CHECK: store float %x.1
+ // CHECK: %[[A:.+]] = load float
+ // CHECK: %[[B:.+]] = load double
+ // CHECK: %[[P:.+]] = insertvalue { float, double } poison, float %[[A]], 0
+ // CHECK: insertvalue { float, double } %[[P]], double %[[B]], 1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_issue_110005(
+#[no_mangle]
+pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option<Box<[u8]>> {
+ // CHECK: store i64 %x.0
+ // CHECK: %[[WIDER:.+]] = zext i1 %x.1 to i8
+ // CHECK: store i8 %[[WIDER]]
+ // CHECK: load ptr
+ // CHECK: load i64
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_pair_to_dst_ref(
+#[no_mangle]
+pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] {
+ // CHECK: %0 = inttoptr i64 %x.0 to ptr
+ // CHECK: %1 = insertvalue { ptr, i64 } poison, ptr %0, 0
+ // CHECK: %2 = insertvalue { ptr, i64 } %1, i64 %x.1, 1
+ // CHECK: ret { ptr, i64 } %2
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_issue_109992(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
+ // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+ // CHECK: start
+ // CHECK-NEXT: ret void
+ mir!{
+ {
+ RET = CastTransmute(x);
+ Return()
+ }
+ }
+}
+
+// CHECK-LABEL: @check_maybe_uninit_pair(i16 %x.0, i64 %x.1)
+#[no_mangle]
+pub unsafe fn check_maybe_uninit_pair(
+ x: (MaybeUninit<u16>, MaybeUninit<u64>),
+) -> (MaybeUninit<i64>, MaybeUninit<i16>) {
+ // Thanks to `MaybeUninit` this is actually defined behaviour,
+ // unlike the examples above with pairs of primitives.
+
+ // CHECK: store i16 %x.0
+ // CHECK: store i64 %x.1
+ // CHECK: load i64
+ // CHECK-NOT: noundef
+ // CHECK: load i16
+ // CHECK-NOT: noundef
+ // CHECK: ret { i64, i16 }
+ transmute(x)
+}
+
+#[repr(align(8))]
+pub struct HighAlignScalar(u8);
+
+// CHECK-LABEL: @check_to_overalign(
+#[no_mangle]
+pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar {
+ // CHECK: %0 = alloca %HighAlignScalar, align 8
+ // CHECK: store i64 %x, ptr %0, align 8
+ // CHECK: %1 = load i64, ptr %0, align 8
+ // CHECK: ret i64 %1
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_overalign(
+#[no_mangle]
+pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 {
+ // CHECK: %x = alloca %HighAlignScalar, align 8
+ // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 8
+ // CHECK: ret i64 %[[VAL]]
+ transmute(x)
+}
diff --git a/tests/codegen/auxiliary/static_dllimport_aux.rs b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
index afb0dc42f..afb0dc42f 100644
--- a/tests/codegen/auxiliary/static_dllimport_aux.rs
+++ b/tests/codegen/issues/auxiliary/static_dllimport_aux.rs
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/issue-103285-ptr-addr-overflow-check.rs b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
index a3499babe..a3499babe 100644
--- a/tests/codegen/issue-103285-ptr-addr-overflow-check.rs
+++ b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs
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/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
index f19d7031b..f19d7031b 100644
--- a/tests/codegen/issue-103840.rs
+++ b/tests/codegen/issues/issue-103840.rs
diff --git a/tests/codegen/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
index d54ac9e33..d54ac9e33 100644
--- a/tests/codegen/issue-105386-ub-in-debuginfo.rs
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
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/issue-13018.rs b/tests/codegen/issues/issue-13018.rs
index b70ea1f48..b70ea1f48 100644
--- a/tests/codegen/issue-13018.rs
+++ b/tests/codegen/issues/issue-13018.rs
diff --git a/tests/codegen/issue-15953.rs b/tests/codegen/issues/issue-15953.rs
index 28d284289..28d284289 100644
--- a/tests/codegen/issue-15953.rs
+++ b/tests/codegen/issues/issue-15953.rs
diff --git a/tests/codegen/issue-27130.rs b/tests/codegen/issues/issue-27130.rs
index e5ee94e1f..e5ee94e1f 100644
--- a/tests/codegen/issue-27130.rs
+++ b/tests/codegen/issues/issue-27130.rs
diff --git a/tests/codegen/issue-32031.rs b/tests/codegen/issues/issue-32031.rs
index abef92c19..abef92c19 100644
--- a/tests/codegen/issue-32031.rs
+++ b/tests/codegen/issues/issue-32031.rs
diff --git a/tests/codegen/issue-32364.rs b/tests/codegen/issues/issue-32364.rs
index 85493a4bb..85493a4bb 100644
--- a/tests/codegen/issue-32364.rs
+++ b/tests/codegen/issues/issue-32364.rs
diff --git a/tests/codegen/issue-34634.rs b/tests/codegen/issues/issue-34634.rs
index f53fa240c..f53fa240c 100644
--- a/tests/codegen/issue-34634.rs
+++ b/tests/codegen/issues/issue-34634.rs
diff --git a/tests/codegen/issue-34947-pow-i32.rs b/tests/codegen/issues/issue-34947-pow-i32.rs
index 653da8e8b..653da8e8b 100644
--- a/tests/codegen/issue-34947-pow-i32.rs
+++ b/tests/codegen/issues/issue-34947-pow-i32.rs
diff --git a/tests/codegen/issue-37945.rs b/tests/codegen/issues/issue-37945.rs
index fe54375bb..4f386d335 100644
--- a/tests/codegen/issue-37945.rs
+++ b/tests/codegen/issues/issue-37945.rs
@@ -1,9 +1,6 @@
// compile-flags: -O -Zmerge-functions=disabled
-// ignore-x86
-// ignore-arm
-// ignore-emscripten
-// ignore-gnux32
-// ignore 32-bit platforms (LLVM has a bug with them)
+// ignore-32bit LLVM has a bug with them
+// ignore-debug
// Check that LLVM understands that `Iter` pointer is not null. Issue #37945.
diff --git a/tests/codegen/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs
index 1a3923f1b..1a3923f1b 100644
--- a/tests/codegen/issue-44056-macos-tls-align.rs
+++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs
diff --git a/tests/codegen/issue-45222.rs b/tests/codegen/issues/issue-45222.rs
index e9b05e648..e9b05e648 100644
--- a/tests/codegen/issue-45222.rs
+++ b/tests/codegen/issues/issue-45222.rs
diff --git a/tests/codegen/issue-45466.rs b/tests/codegen/issues/issue-45466.rs
index c79542767..c79542767 100644
--- a/tests/codegen/issue-45466.rs
+++ b/tests/codegen/issues/issue-45466.rs
diff --git a/tests/codegen/issue-45964-bounds-check-slice-pos.rs b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
index 1daa213fc..1daa213fc 100644
--- a/tests/codegen/issue-45964-bounds-check-slice-pos.rs
+++ b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs
diff --git a/tests/codegen/issue-47278.rs b/tests/codegen/issues/issue-47278.rs
index 9076274f4..9076274f4 100644
--- a/tests/codegen/issue-47278.rs
+++ b/tests/codegen/issues/issue-47278.rs
diff --git a/tests/codegen/issue-47442.rs b/tests/codegen/issues/issue-47442.rs
index 6944336d3..6944336d3 100644
--- a/tests/codegen/issue-47442.rs
+++ b/tests/codegen/issues/issue-47442.rs
diff --git a/tests/codegen/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs
index 4dc9ebfeb..4dc9ebfeb 100644
--- a/tests/codegen/issue-56267-2.rs
+++ b/tests/codegen/issues/issue-56267-2.rs
diff --git a/tests/codegen/issue-56267.rs b/tests/codegen/issues/issue-56267.rs
index 7bdd25779..7bdd25779 100644
--- a/tests/codegen/issue-56267.rs
+++ b/tests/codegen/issues/issue-56267.rs
diff --git a/tests/codegen/issue-56927.rs b/tests/codegen/issues/issue-56927.rs
index 044d72181..044d72181 100644
--- a/tests/codegen/issue-56927.rs
+++ b/tests/codegen/issues/issue-56927.rs
diff --git a/tests/codegen/issue-58881.rs b/tests/codegen/issues/issue-58881.rs
index 00f8953d9..00f8953d9 100644
--- a/tests/codegen/issue-58881.rs
+++ b/tests/codegen/issues/issue-58881.rs
diff --git a/tests/codegen/issue-59352.rs b/tests/codegen/issues/issue-59352.rs
index d271fe027..d271fe027 100644
--- a/tests/codegen/issue-59352.rs
+++ b/tests/codegen/issues/issue-59352.rs
diff --git a/tests/codegen/issue-69101-bounds-check.rs b/tests/codegen/issues/issue-69101-bounds-check.rs
index a3aca3a29..a3aca3a29 100644
--- a/tests/codegen/issue-69101-bounds-check.rs
+++ b/tests/codegen/issues/issue-69101-bounds-check.rs
diff --git a/tests/codegen/issue-73031.rs b/tests/codegen/issues/issue-73031.rs
index a09c4bcfb..a09c4bcfb 100644
--- a/tests/codegen/issue-73031.rs
+++ b/tests/codegen/issues/issue-73031.rs
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/issue-73338-effecient-cmp.rs b/tests/codegen/issues/issue-73338-effecient-cmp.rs
index 85c2bbfd0..85c2bbfd0 100644
--- a/tests/codegen/issue-73338-effecient-cmp.rs
+++ b/tests/codegen/issues/issue-73338-effecient-cmp.rs
diff --git a/tests/codegen/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
index 8d07a67a1..8d07a67a1 100644
--- a/tests/codegen/issue-73396-bounds-check-after-position.rs
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
diff --git a/tests/codegen/issue-73827-bounds-check-index-in-subexpr.rs b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
index 1ad05906e..1ad05906e 100644
--- a/tests/codegen/issue-73827-bounds-check-index-in-subexpr.rs
+++ b/tests/codegen/issues/issue-73827-bounds-check-index-in-subexpr.rs
diff --git a/tests/codegen/issue-75525-bounds-checks.rs b/tests/codegen/issues/issue-75525-bounds-checks.rs
index 2d363d8f7..2d363d8f7 100644
--- a/tests/codegen/issue-75525-bounds-checks.rs
+++ b/tests/codegen/issues/issue-75525-bounds-checks.rs
diff --git a/tests/codegen/issue-75546.rs b/tests/codegen/issues/issue-75546.rs
index 470a9e040..470a9e040 100644
--- a/tests/codegen/issue-75546.rs
+++ b/tests/codegen/issues/issue-75546.rs
diff --git a/tests/codegen/issue-75659.rs b/tests/codegen/issues/issue-75659.rs
index 9394868c0..9394868c0 100644
--- a/tests/codegen/issue-75659.rs
+++ b/tests/codegen/issues/issue-75659.rs
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/issue-77812.rs b/tests/codegen/issues/issue-77812.rs
index 4cc824145..4cc824145 100644
--- a/tests/codegen/issue-77812.rs
+++ b/tests/codegen/issues/issue-77812.rs
diff --git a/tests/codegen/issue-81408-dllimport-thinlto-windows.rs b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
index 0b6ab4f7e..0b6ab4f7e 100644
--- a/tests/codegen/issue-81408-dllimport-thinlto-windows.rs
+++ b/tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs
diff --git a/tests/codegen/issue-84268.rs b/tests/codegen/issues/issue-84268.rs
index 7ca195447..7ca195447 100644
--- a/tests/codegen/issue-84268.rs
+++ b/tests/codegen/issues/issue-84268.rs
diff --git a/tests/codegen/issue-85872-multiple-reverse.rs b/tests/codegen/issues/issue-85872-multiple-reverse.rs
index 591a1aca7..591a1aca7 100644
--- a/tests/codegen/issue-85872-multiple-reverse.rs
+++ b/tests/codegen/issues/issue-85872-multiple-reverse.rs
diff --git a/tests/codegen/issue-86106.rs b/tests/codegen/issues/issue-86106.rs
index 9ccbcb24f..9ccbcb24f 100644
--- a/tests/codegen/issue-86106.rs
+++ b/tests/codegen/issues/issue-86106.rs
diff --git a/tests/codegen/issue-96274.rs b/tests/codegen/issues/issue-96274.rs
index 28bfcce0d..28bfcce0d 100644
--- a/tests/codegen/issue-96274.rs
+++ b/tests/codegen/issues/issue-96274.rs
diff --git a/tests/codegen/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
index 0413ed6b2..0413ed6b2 100644
--- a/tests/codegen/issue-96497-slice-size-nowrap.rs
+++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs
diff --git a/tests/codegen/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
index 12ace5fff..12ace5fff 100644
--- a/tests/codegen/issue-98156-const-arg-temp-lifetime.rs
+++ b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
diff --git a/tests/codegen/issue-98294-get-mut-copy-from-slice-opt.rs b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
index 7da29cd79..7da29cd79 100644
--- a/tests/codegen/issue-98294-get-mut-copy-from-slice-opt.rs
+++ b/tests/codegen/issues/issue-98294-get-mut-copy-from-slice-opt.rs
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
+ }
+}
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
new file mode 100644
index 000000000..f6898e2f7
--- /dev/null
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -0,0 +1,36 @@
+// This test ensures that `mem::replace::<T>` only ever calls `@llvm.memcpy`
+// with `size_of::<T>()` as the size, and never goes through any wrapper that
+// may e.g. multiply `size_of::<T>()` with a variable "count" (which is only
+// known to be `1` after inlining).
+
+// compile-flags: -C no-prepopulate-passes -Zinline-mir=no
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[repr(C, align(8))]
+pub struct Big([u64; 7]);
+pub fn replace_big(dst: &mut Big, src: Big) -> Big {
+ // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s.
+ std::mem::replace(dst, src)
+}
+
+// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
+// the entire output, are the direct calls we want, from `ptr::replace`.
+
+// CHECK-NOT: call void @llvm.memcpy
+
+// For a large type, we expect exactly three `memcpy`s
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
+ // CHECK-NOT: alloca
+ // CHECK: alloca %Big
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+ // CHECK-NOT: call void @llvm.memcpy
+
+// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-direct-memcpy.rs b/tests/codegen/mem-replace-direct-memcpy.rs
index e8bbf0e1b..83babab4f 100644
--- a/tests/codegen/mem-replace-direct-memcpy.rs
+++ b/tests/codegen/mem-replace-direct-memcpy.rs
@@ -13,12 +13,21 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
}
// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
-// the entire output, are the two direct calls we want, from `ptr::replace`.
+// the entire output, are the direct calls we want, from `ptr::replace`.
// 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 %{{.*}}, i{{.*}} 1, i1 false)
-// CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
+
+// For a small type, we expect one each of `load`/`store`/`memcpy` instead
+// CHECK-LABEL: define internal noundef i8 @{{.+}}mem{{.+}}replace
+ // CHECK-NOT: alloca
+ // CHECK: alloca i8
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: load i8
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: store i8
+ // CHECK-NOT: call void @llvm.memcpy
+ // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
+ // CHECK-NOT: call void @llvm.memcpy
+
// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs
index 22abe06e7..1d1f0a386 100644
--- a/tests/codegen/optimize-attr-1.rs
+++ b/tests/codegen/optimize-attr-1.rs
@@ -8,7 +8,6 @@
// CHECK-LABEL: define{{.*}}i32 @nothing
// CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 4
// SIZE-OPT: ret i32 4
// SPEEC-OPT: ret i32 4
#[no_mangle]
@@ -18,7 +17,6 @@ pub fn nothing() -> i32 {
// CHECK-LABEL: define{{.*}}i32 @size
// CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 6
// SIZE-OPT: ret i32 6
// SPEED-OPT: ret i32 6
#[optimize(size)]
@@ -31,7 +29,6 @@ pub fn size() -> i32 {
// NO-OPT-SAME: [[NOTHING_ATTRS]]
// SPEED-OPT-SAME: [[NOTHING_ATTRS]]
// SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]]
-// NO-OPT: ret i32 8
// SIZE-OPT: ret i32 8
// SPEED-OPT: ret i32 8
#[optimize(speed)]
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index d5077dbf6..d735d5583 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// compile-flags: -O -Z randomize-layout=no
// only-x86_64
#![crate_type = "lib"]
@@ -12,17 +12,25 @@ use core::option::Option;
// CHECK-LABEL: @u64_opt_as_slice
#[no_mangle]
pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
- // CHECK: start:
// CHECK-NOT: select
- // CHECK: ret
+ // CHECK-NOT: br
+ // CHECK-NOT: switch
+ // CHECK-NOT: icmp
o.as_slice()
}
// CHECK-LABEL: @nonzero_u64_opt_as_slice
#[no_mangle]
pub fn nonzero_u64_opt_as_slice(o: &Option<NonZeroU64>) -> &[NonZeroU64] {
- // CHECK: start:
// CHECK-NOT: select
- // CHECK: ret
+ // CHECK-NOT: br
+ // CHECK-NOT: switch
+ // CHECK-NOT: icmp
+ // CHECK: %[[NZ:.+]] = icmp ne i64 %{{.+}}, 0
+ // CHECK-NEXT: zext i1 %[[NZ]] to i64
+ // CHECK-NOT: select
+ // CHECK-NOT: br
+ // CHECK-NOT: switch
+ // CHECK-NOT: icmp
o.as_slice()
}
diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs
new file mode 100644
index 000000000..e1e327266
--- /dev/null
+++ b/tests/codegen/ptr-read-metadata.rs
@@ -0,0 +1,96 @@
+// compile-flags: -O -Z merge-functions=disabled
+// no-system-llvm
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Ensure that various forms of reading pointers correctly annotate the `load`s
+// with `!noundef` and `!range` metadata to enable extra optimization.
+
+use std::mem::MaybeUninit;
+
+// CHECK-LABEL: define noundef i8 @copy_byte(
+#[no_mangle]
+pub unsafe fn copy_byte(p: *const u8) -> u8 {
+ // CHECK-NOT: load
+ // CHECK: load i8, ptr %p, align 1
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ *p
+}
+
+// CHECK-LABEL: define noundef i8 @read_byte(
+#[no_mangle]
+pub unsafe fn read_byte(p: *const u8) -> u8 {
+ // CHECK-NOT: load
+ // CHECK: load i8, ptr %p, align 1
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ p.read()
+}
+
+// CHECK-LABEL: define i8 @read_byte_maybe_uninit(
+#[no_mangle]
+pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u8> {
+ // CHECK-NOT: load
+ // CHECK: load i8, ptr %p, align 1
+ // CHECK-NOT: noundef
+ // CHECK-NOT: load
+ p.read()
+}
+
+// CHECK-LABEL: define noundef i8 @read_byte_assume_init(
+#[no_mangle]
+pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
+ // CHECK-NOT: load
+ // CHECK: load i8, ptr %p, align 1
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ p.assume_init_read()
+}
+
+// CHECK-LABEL: define noundef i32 @copy_char(
+#[no_mangle]
+pub unsafe fn copy_char(p: *const char) -> char {
+ // CHECK-NOT: load
+ // CHECK: load i32, ptr %p
+ // CHECK-SAME: !range ![[RANGE:[0-9]+]]
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ *p
+}
+
+// CHECK-LABEL: define noundef i32 @read_char(
+#[no_mangle]
+pub unsafe fn read_char(p: *const char) -> char {
+ // CHECK-NOT: load
+ // CHECK: load i32, ptr %p
+ // CHECK-SAME: !range ![[RANGE]]
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ p.read()
+}
+
+// CHECK-LABEL: define i32 @read_char_maybe_uninit(
+#[no_mangle]
+pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit<char> {
+ // CHECK-NOT: load
+ // CHECK: load i32, ptr %p
+ // CHECK-NOT: range
+ // CHECK-NOT: noundef
+ // CHECK-NOT: load
+ p.read()
+}
+
+// CHECK-LABEL: define noundef i32 @read_char_assume_init(
+#[no_mangle]
+pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char {
+ // CHECK-NOT: load
+ // CHECK: load i32, ptr %p
+ // CHECK-SAME: !range ![[RANGE]]
+ // CHECK-SAME: !noundef !
+ // CHECK-NOT: load
+ p.assume_init_read()
+}
+
+// CHECK: ![[RANGE]] = !{i32 0, i32 1114112}
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
index 6c0cd6997..f1e1dd69b 100644
--- a/tests/codegen/remap_path_prefix/main.rs
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
include!("aux_mod.rs");
// Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc_92a59126a55aa3c0019b6c8a007fe001 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
pub static FILE_PATH: &'static str = file!();
fn main() {
diff --git a/tests/codegen/repr-transparent-aggregates-2.rs b/tests/codegen/repr-transparent-aggregates-2.rs
index df7e88f08..e9fa5143b 100644
--- a/tests/codegen/repr-transparent-aggregates-2.rs
+++ b/tests/codegen/repr-transparent-aggregates-2.rs
@@ -6,7 +6,6 @@
// ignore-mips64
// ignore-powerpc
// ignore-powerpc64
-// ignore-powerpc64le
// ignore-riscv64 see codegen/riscv-abi
// ignore-s390x
// ignore-sparc
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index 7c77398df..fd488a14b 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -4,7 +4,8 @@
#![crate_type = "lib"]
#![allow(non_camel_case_types)]
-#![feature(repr_simd, platform_intrinsics, min_const_generics)]
+#![feature(repr_simd, platform_intrinsics)]
+#![feature(inline_const)]
#[repr(simd)]
#[derive(Copy, Clone)]
@@ -18,23 +19,65 @@ pub struct T([f32; 4]);
#[derive(Copy, Clone)]
pub struct U(f32, f32, f32, f32);
+// CHECK-LABEL: @array_align(
+#[no_mangle]
+pub fn array_align() -> usize {
+ // CHECK: ret [[USIZE:i[0-9]+]] [[ARRAY_ALIGN:[0-9]+]]
+ const { std::mem::align_of::<f32>() }
+}
+
+// CHECK-LABEL: @vector_align(
+#[no_mangle]
+pub fn vector_align() -> usize {
+ // CHECK: ret [[USIZE]] [[VECTOR_ALIGN:[0-9]+]]
+ const { std::mem::align_of::<U>() }
+}
+
// CHECK-LABEL: @build_array_s
#[no_mangle]
pub fn build_array_s(x: [f32; 4]) -> S<4> {
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
+ // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
S::<4>(x)
}
+// CHECK-LABEL: @build_array_transmute_s
+#[no_mangle]
+pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> {
+ // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
+ // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
+ unsafe { std::mem::transmute(x) }
+}
+
// CHECK-LABEL: @build_array_t
#[no_mangle]
pub fn build_array_t(x: [f32; 4]) -> T {
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
+ // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false)
T(x)
}
+// CHECK-LABEL: @build_array_transmute_t
+#[no_mangle]
+pub fn build_array_transmute_t(x: [f32; 4]) -> T {
+ // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
+ // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
+ unsafe { std::mem::transmute(x) }
+}
+
// CHECK-LABEL: @build_array_u
#[no_mangle]
pub fn build_array_u(x: [f32; 4]) -> U {
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
+ // CHECK: store float %a, {{.+}}, align [[VECTOR_ALIGN]]
+ // CHECK: store float %b, {{.+}}, align [[ARRAY_ALIGN]]
+ // CHECK: store float %c, {{.+}}, align
+ // CHECK: store float %d, {{.+}}, align [[ARRAY_ALIGN]]
+ let [a, b, c, d] = x;
+ U(a, b, c, d)
+}
+
+// CHECK-LABEL: @build_array_transmute_u
+#[no_mangle]
+pub fn build_array_transmute_u(x: [f32; 4]) -> U {
+ // CHECK: %[[VAL:.+]] = load <4 x float>, {{ptr %x|.+>\* %.+}}, align [[ARRAY_ALIGN]]
+ // CHECK: store <4 x float> %[[VAL:.+]], {{ptr %0|.+>\* %.+}}, align [[VECTOR_ALIGN]]
unsafe { std::mem::transmute(x) }
}
diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs
index 04314dc29..db2aa20bd 100644
--- a/tests/codegen/simd-wide-sum.rs
+++ b/tests/codegen/simd-wide-sum.rs
@@ -1,4 +1,4 @@
-// compile-flags: -C opt-level=3 --edition=2021
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
// only-x86_64
// ignore-debug: the debug assertions get in the way
diff --git a/tests/codegen/slice-indexing.rs b/tests/codegen/slice-indexing.rs
new file mode 100644
index 000000000..c40d59fb0
--- /dev/null
+++ b/tests/codegen/slice-indexing.rs
@@ -0,0 +1,35 @@
+// compile-flags: -O
+// only-64bit (because the LLVM type of i64 for usize shows up)
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::ops::Range;
+
+// CHECK-LABEL: @index_by_range(
+#[no_mangle]
+pub fn index_by_range(x: &[u16], r: Range<usize>) -> &[u16] {
+ // CHECK: sub nuw i64
+ &x[r]
+}
+
+// CHECK-LABEL: @get_unchecked_by_range(
+#[no_mangle]
+pub unsafe fn get_unchecked_by_range(x: &[u16], r: Range<usize>) -> &[u16] {
+ // CHECK: sub nuw i64
+ x.get_unchecked(r)
+}
+
+// CHECK-LABEL: @index_mut_by_range(
+#[no_mangle]
+pub fn index_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut [i32] {
+ // CHECK: sub nuw i64
+ &mut x[r]
+}
+
+// CHECK-LABEL: @get_unchecked_mut_by_range(
+#[no_mangle]
+pub unsafe fn get_unchecked_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut [i32] {
+ // CHECK: sub nuw i64
+ x.get_unchecked_mut(r)
+}
diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs
index 260dcbac0..af2cef472 100644
--- a/tests/codegen/transmute-scalar.rs
+++ b/tests/codegen/transmute-scalar.rs
@@ -1,80 +1,57 @@
// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 # this test assumes `ptr`s and thus no `pointercast`s
#![crate_type = "lib"]
-// FIXME(eddyb) all of these tests show memory stores and loads, even after a
-// scalar `bitcast`, more special-casing is required to remove `alloca` usage.
+// With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type,
+// without needing to pointercast, and SRoA will turn that into a `bitcast`.
+// Thus memory-to-memory transmutes don't need to generate them ourselves.
+
+// However, `bitcast`s and `ptrtoint`s and `inttoptr`s are still worth doing when
+// that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`.
// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float noundef %x)
-// CHECK: store i32 %{{.*}}, {{.*}} %0
-// CHECK-NEXT: %[[RES:.*]] = load i32, {{.*}} %0
-// CHECK: ret i32 %[[RES]]
+// CHECK: %0 = bitcast float %x to i32
+// CHECK-NEXT: ret i32 %0
#[no_mangle]
pub fn f32_to_bits(x: f32) -> u32 {
unsafe { std::mem::transmute(x) }
}
// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 noundef zeroext %b)
-// CHECK: %1 = zext i1 %b to i8
-// CHECK-NEXT: store i8 %1, {{.*}} %0
-// CHECK-NEXT: %2 = load i8, {{.*}} %0
-// CHECK: ret i8 %2
+// CHECK: %0 = zext i1 %b to i8
+// CHECK-NEXT: ret i8 %0
#[no_mangle]
pub fn bool_to_byte(b: bool) -> u8 {
unsafe { std::mem::transmute(b) }
}
// CHECK-LABEL: define{{.*}}noundef zeroext i1 @byte_to_bool(i8 noundef %byte)
-// CHECK: %1 = trunc i8 %byte to i1
-// CHECK-NEXT: %2 = zext i1 %1 to i8
-// CHECK-NEXT: store i8 %2, {{.*}} %0
-// CHECK-NEXT: %3 = load i8, {{.*}} %0
-// CHECK-NEXT: %4 = trunc i8 %3 to i1
-// CHECK: ret i1 %4
+// CHECK: %0 = trunc i8 %byte to i1
+// CHECK-NEXT: ret i1 %0
#[no_mangle]
pub unsafe fn byte_to_bool(byte: u8) -> bool {
std::mem::transmute(byte)
}
-// CHECK-LABEL: define{{.*}}{{i8\*|ptr}} @ptr_to_ptr({{i16\*|ptr}} noundef %p)
-// CHECK: store {{i8\*|ptr}} %{{.*}}, {{.*}} %0
-// CHECK-NEXT: %[[RES:.*]] = load {{i8\*|ptr}}, {{.*}} %0
-// CHECK: ret {{i8\*|ptr}} %[[RES]]
+// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr noundef %p)
+// CHECK: ret ptr %p
#[no_mangle]
pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
unsafe { std::mem::transmute(p) }
}
-// HACK(eddyb) scalar `transmute`s between pointers and non-pointers are
-// currently not special-cased like other scalar `transmute`s, because
-// LLVM requires specifically `ptrtoint`/`inttoptr` instead of `bitcast`.
-//
-// Tests below show the non-special-cased behavior (with the possible
-// future special-cased instructions in the "NOTE(eddyb)" comments).
-
-// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int({{i16\*|ptr}} noundef %p)
-
-// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
-// %2 = ptrtoint i16* %p to [[USIZE]]
-// store [[USIZE]] %2, [[USIZE]]* %0
-// CHECK: store {{i16\*|ptr}} %p, {{.*}}
-
-// CHECK-NEXT: %[[RES:.*]] = load [[USIZE]], {{.*}} %0
-// CHECK: ret [[USIZE]] %[[RES]]
+// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr noundef %p)
+// CHECK: %0 = ptrtoint ptr %p to [[USIZE]]
+// CHECK-NEXT: ret [[USIZE]] %0
#[no_mangle]
pub fn ptr_to_int(p: *mut u16) -> usize {
unsafe { std::mem::transmute(p) }
}
-// CHECK: define{{.*}}{{i16\*|ptr}} @int_to_ptr([[USIZE]] noundef %i)
-
-// NOTE(eddyb) see above, the following two CHECK lines should ideally be this:
-// %2 = inttoptr [[USIZE]] %i to i16*
-// store i16* %2, i16** %0
-// CHECK: store [[USIZE]] %i, {{.*}}
-
-// CHECK-NEXT: %[[RES:.*]] = load {{i16\*|ptr}}, {{.*}} %0
-// CHECK: ret {{i16\*|ptr}} %[[RES]]
+// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] noundef %i)
+// CHECK: %0 = inttoptr [[USIZE]] %i to ptr
+// CHECK-NEXT: ret ptr %0
#[no_mangle]
pub fn int_to_ptr(i: usize) -> *mut u16 {
unsafe { std::mem::transmute(i) }
diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs
index d4715efad..53841df32 100644
--- a/tests/codegen/var-names.rs
+++ b/tests/codegen/var-names.rs
@@ -9,7 +9,7 @@ pub fn test(a: u32, b: u32) -> u32 {
// CHECK: %c = add i32 %a, %b
let d = c;
let e = d * a;
- // CHECK-NEXT: %e = mul i32 %c, %a
+ // CHECK-NEXT: %0 = mul i32 %c, %a
e
- // CHECK-NEXT: ret i32 %e
+ // CHECK-NEXT: ret i32 %0
}
diff --git a/tests/codegen/vec-as-ptr.rs b/tests/codegen/vec-as-ptr.rs
new file mode 100644
index 000000000..8ff7ba9cb
--- /dev/null
+++ b/tests/codegen/vec-as-ptr.rs
@@ -0,0 +1,19 @@
+// compile-flags: -O -Zmerge-functions=disabled
+
+#![crate_type = "lib"]
+
+// Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
+// pointer is nonnull.
+// CHECK: nonnull {{i8\*|ptr}} @vec_as_ptr
+#[no_mangle]
+pub fn vec_as_ptr(v: &Vec<u8>) -> *const u8 {
+ v.as_ptr()
+}
+
+// Test that even though we return a *const u8 not a &[u8] or a NonNull<u8>, LLVM knows that this
+// pointer is nonnull.
+// CHECK: nonnull {{i8\*|ptr}} @vec_as_mut_ptr
+#[no_mangle]
+pub fn vec_as_mut_ptr(v: &mut Vec<u8>) -> *mut u8 {
+ v.as_mut_ptr()
+}
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
index 999260422..d68067ceb 100644
--- a/tests/codegen/vec-in-place.rs
+++ b/tests/codegen/vec-in-place.rs
@@ -1,11 +1,13 @@
// ignore-debug: the debug assertions get in the way
// compile-flags: -O -Z merge-functions=disabled
+// min-llvm-version: 16
#![crate_type = "lib"]
// Ensure that trivial casts of vec elements are O(1)
pub struct Wrapper<T>(T);
+// previously repr(C) caused the optimization to fail
#[repr(C)]
pub struct Foo {
a: u64,
@@ -14,9 +16,8 @@ pub struct Foo {
d: u64,
}
-// Going from an aggregate struct to another type currently requires Copy to
-// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
-// reliably recognize the loops as noop for repr(C) or non-Copy structs.
+// implementing Copy exercises the TrustedRandomAccess specialization inside the in-place
+// specialization
#[derive(Copy, Clone)]
pub struct Bar {
a: u64,
@@ -25,6 +26,14 @@ pub struct Bar {
d: u64,
}
+// this exercises the try-fold codepath
+pub struct Baz {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+}
+
// CHECK-LABEL: @vec_iterator_cast_primitive
#[no_mangle]
pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
@@ -52,18 +61,29 @@ pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
// CHECK-LABEL: @vec_iterator_cast_aggregate
#[no_mangle]
pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
- // FIXME These checks should be the same as other functions.
- // CHECK-NOT: @__rust_alloc
- // CHECK-NOT: @__rust_alloc
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
}
-// CHECK-LABEL: @vec_iterator_cast_deaggregate
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_tra
#[no_mangle]
-pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> {
- // FIXME These checks should be the same as other functions.
- // CHECK-NOT: @__rust_alloc
- // CHECK-NOT: @__rust_alloc
+pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
+
+ // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+ // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+ // the UCG may add additional guarantees for homogenous types in the future that would make this
+ // correct.
+ vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate_fold
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
// Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
// This currently is not guaranteed for repr(Rust) types, but it happens to work here and
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index aa6589dc3..b3c3483fe 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -1,3 +1,8 @@
+// revisions: old new
+// LLVM 17 realizes double panic is not possible and doesn't generate calls
+// to panic_cannot_unwind.
+// [old]ignore-llvm-version: 17 - 99
+// [new]min-llvm-version: 17
// compile-flags: -O
// ignore-debug: the debug assertions get in the way
#![crate_type = "lib"]
@@ -18,11 +23,11 @@ pub fn shrink_to_fit(vec: &mut Vec<u32>) {
pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
// CHECK-NOT: panic
- // Call to panic_cannot_unwind in case of double-panic is expected,
- // but other panics are not.
+ // Call to panic_cannot_unwind in case of double-panic is expected
+ // on LLVM 16 and older, but other panics are not.
// CHECK: cleanup
- // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind
- // CHECK-NEXT: panic_cannot_unwind
+ // old-NEXT: ; call core::panicking::panic_cannot_unwind
+ // old-NEXT: panic_cannot_unwind
// CHECK-NOT: panic
vec.into_boxed_slice()
@@ -34,14 +39,14 @@ pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
// CHECK-NOT: panic
// Call to panic_cannot_unwind in case of double-panic is expected,
- // but other panics are not.
+ // on LLVM 16 and older, but other panics are not.
// CHECK: cleanup
- // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind
- // CHECK-NEXT: panic_cannot_unwind
+ // old-NEXT: ; call core::panicking::panic_cannot_unwind
+ // old-NEXT: panic_cannot_unwind
// CHECK-NOT: panic
iter.iter().copied().collect()
}
-// CHECK: ; core::panicking::panic_cannot_unwind
-// CHECK: declare void @{{.*}}panic_cannot_unwind
+// old: ; core::panicking::panic_cannot_unwind
+// old: declare void @{{.*}}panic_cannot_unwind
diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs
index 4cf7e12fe..f22176a02 100644
--- a/tests/codegen/virtual-function-elimination.rs
+++ b/tests/codegen/virtual-function-elimination.rs
@@ -1,5 +1,6 @@
// compile-flags: -Zvirtual-function-elimination -Clto -O -Csymbol-mangling-version=v0
// ignore-32bit
+// ignore-debug
// CHECK: @vtable.0 = {{.*}}, !type ![[TYPE0:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
// CHECK: @vtable.1 = {{.*}}, !type ![[TYPE1:[0-9]+]], !vcall_visibility ![[VCALL_VIS0:[0-9]+]]
@@ -81,7 +82,7 @@ fn taking_u(u: &dyn U) -> i32 {
}
pub fn taking_v(v: &dyn V) -> i32 {
- // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V")
+ // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCs64ITQYi9761_28virtual_function_elimination1V")
v.public_function()
}
@@ -96,5 +97,5 @@ pub fn main() {
// CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"}
// CHECK: ![[VCALL_VIS0]] = !{i64 2}
// CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"}
-// CHECK: ![[TYPE2]] = !{i64 0, !"NtCsfRpWlKdQPZn_28virtual_function_elimination1V"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"NtCs64ITQYi9761_28virtual_function_elimination1V"}
// CHECK: ![[VCALL_VIS2]] = !{i64 1}