diff options
Diffstat (limited to 'tests/codegen/intrinsics/transmute-niched.rs')
-rw-r--r-- | tests/codegen/intrinsics/transmute-niched.rs | 184 |
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) +} |