summaryrefslogtreecommitdiffstats
path: root/tests/codegen/intrinsics
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /tests/codegen/intrinsics
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/codegen/intrinsics')
-rw-r--r--tests/codegen/intrinsics/offset.rs34
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs184
-rw-r--r--tests/codegen/intrinsics/transmute.rs50
3 files changed, 231 insertions, 37 deletions
diff --git a/tests/codegen/intrinsics/offset.rs b/tests/codegen/intrinsics/offset.rs
new file mode 100644
index 000000000..7fc4f4498
--- /dev/null
+++ b/tests/codegen/intrinsics/offset.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -C no-prepopulate-passes
+// min-llvm-version: 15.0 (because we're using opaque pointers)
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::offset;
+
+// CHECK-LABEL: ptr @offset_zst
+// CHECK-SAME: (ptr noundef %p, [[SIZE:i[0-9]+]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () {
+ // CHECK-NOT: getelementptr
+ // CHECK: ret ptr %p
+ offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_isize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
+ // CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d
+ // CHECK-NEXT: ret ptr %[[R]]
+ offset(p, d)
+}
+
+// CHECK-LABEL: ptr @offset_usize
+// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
+#[no_mangle]
+pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 {
+ // CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d
+ // CHECK-NEXT: ret ptr %[[R]]
+ offset(p, d)
+}
diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs
new file mode 100644
index 000000000..69e9b1d12
--- /dev/null
+++ b/tests/codegen/intrinsics/transmute-niched.rs
@@ -0,0 +1,184 @@
+// revisions: OPT DBG
+// [OPT] compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// [DBG] compile-flags: -C opt-level=0 -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"]
+
+use std::mem::transmute;
+use std::num::NonZeroU32;
+
+#[repr(u8)]
+pub enum SmallEnum {
+ A = 10,
+ B = 11,
+ C = 12,
+}
+
+// CHECK-LABEL: @check_to_enum(
+#[no_mangle]
+pub unsafe fn check_to_enum(x: i8) -> SmallEnum {
+ // OPT: %0 = icmp uge i8 %x, 10
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp ule i8 %x, 12
+ // OPT: call void @llvm.assume(i1 %1)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_enum(
+#[no_mangle]
+pub unsafe fn check_from_enum(x: SmallEnum) -> i8 {
+ // OPT: %0 = icmp uge i8 %x, 10
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp ule i8 %x, 12
+ // OPT: call void @llvm.assume(i1 %1)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_to_ordering(
+#[no_mangle]
+pub unsafe fn check_to_ordering(x: u8) -> std::cmp::Ordering {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_from_ordering(
+#[no_mangle]
+pub unsafe fn check_from_ordering(x: std::cmp::Ordering) -> u8 {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %x
+
+ transmute(x)
+}
+
+#[repr(i32)]
+pub enum Minus100ToPlus100 {
+ A = -100,
+ B = -90,
+ C = -80,
+ D = -70,
+ E = -60,
+ F = -50,
+ G = -40,
+ H = -30,
+ I = -20,
+ J = -10,
+ K = 0,
+ L = 10,
+ M = 20,
+ N = 30,
+ O = 40,
+ P = 50,
+ Q = 60,
+ R = 70,
+ S = 80,
+ T = 90,
+ U = 100,
+}
+
+// CHECK-LABEL: @check_enum_from_char(
+#[no_mangle]
+pub unsafe fn check_enum_from_char(x: char) -> Minus100ToPlus100 {
+ // OPT: %0 = icmp ule i32 %x, 1114111
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp uge i32 %x, -100
+ // OPT: %2 = icmp ule i32 %x, 100
+ // OPT: %3 = or i1 %1, %2
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i32 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_enum_to_char(
+#[no_mangle]
+pub unsafe fn check_enum_to_char(x: Minus100ToPlus100) -> char {
+ // OPT: %0 = icmp uge i32 %x, -100
+ // OPT: %1 = icmp ule i32 %x, 100
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i32 %x, 1114111
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i32 %x
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_swap_pair(
+#[no_mangle]
+pub unsafe fn check_swap_pair(x: (char, NonZeroU32)) -> (NonZeroU32, char) {
+ // OPT: %0 = icmp ule i32 %x.0, 1114111
+ // OPT: call void @llvm.assume(i1 %0)
+ // OPT: %1 = icmp uge i32 %x.0, 1
+ // OPT: call void @llvm.assume(i1 %1)
+ // OPT: %2 = icmp uge i32 %x.1, 1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i32 %x.1, 1114111
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: %[[P1:.+]] = insertvalue { i32, i32 } poison, i32 %x.0, 0
+ // CHECK: %[[P2:.+]] = insertvalue { i32, i32 } %[[P1]], i32 %x.1, 1
+ // CHECK: ret { i32, i32 } %[[P2]]
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_from_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool {
+ // OPT: %0 = icmp uge i8 %x, -1
+ // OPT: %1 = icmp ule i8 %x, 1
+ // OPT: %2 = or i1 %0, %1
+ // OPT: call void @llvm.assume(i1 %2)
+ // OPT: %3 = icmp ule i8 %x, 1
+ // OPT: call void @llvm.assume(i1 %3)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: %[[R:.+]] = trunc i8 %x to i1
+ // CHECK: ret i1 %[[R]]
+
+ transmute(x)
+}
+
+// CHECK-LABEL: @check_bool_to_ordering(
+#[no_mangle]
+pub unsafe fn check_bool_to_ordering(x: bool) -> std::cmp::Ordering {
+ // CHECK: %0 = zext i1 %x to i8
+ // OPT: %1 = icmp ule i8 %0, 1
+ // OPT: call void @llvm.assume(i1 %1)
+ // OPT: %2 = icmp uge i8 %0, -1
+ // OPT: %3 = icmp ule i8 %0, 1
+ // OPT: %4 = or i1 %2, %3
+ // OPT: call void @llvm.assume(i1 %4)
+ // DBG-NOT: icmp
+ // DBG-NOT: assume
+ // CHECK: ret i8 %0
+
+ transmute(x)
+}
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 57f901c67..664e697c2 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -8,10 +8,10 @@
#![feature(inline_const)]
#![allow(unreachable_code)]
-use std::mem::{transmute, MaybeUninit};
+use std::mem::MaybeUninit;
+use std::intrinsics::{transmute, transmute_unchecked};
-// 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.
+// Some of these need custom MIR to not get removed by MIR optimizations.
use std::intrinsics::mir::*;
enum Never {}
@@ -30,59 +30,35 @@ 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()
- }
- }
+ transmute_unchecked(x)
}
// 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()
- }
- }
+ transmute_unchecked(x)
}
// 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()
- }
- }
+ transmute_unchecked(x)
}
// 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()
- }
- }
+ transmute_unchecked(x)
}
// CHECK-LABEL: @check_to_uninhabited(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK: call void @llvm.trap
mir!{
@@ -95,7 +71,7 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
// CHECK-LABEL: @check_from_uninhabited(
#[no_mangle]
-#[custom_mir(dialect = "runtime", phase = "initial")]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
// CHECK: ret i16 poison
mir!{
@@ -169,8 +145,8 @@ pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 {
#[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
+ // CHECK: %[[R:.+]] = trunc i8 %x to i1
+ // CHECK: ret i1 %[[R]]
transmute(x)
}
@@ -178,8 +154,8 @@ pub unsafe fn check_byte_to_bool(x: u8) -> 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
+ // CHECK: %[[R:.+]] = zext i1 %x to i8
+ // CHECK: ret i8 %[[R:.+]]
transmute(x)
}