summaryrefslogtreecommitdiffstats
path: root/tests/codegen/intrinsics/transmute-niched.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/codegen/intrinsics/transmute-niched.rs')
-rw-r--r--tests/codegen/intrinsics/transmute-niched.rs184
1 files changed, 184 insertions, 0 deletions
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)
+}