Skip to content

Commit 7de63ec

Browse files
committed
Fix tests/codegen/transmute-scalar.rs test failure on riscv64
1 parent e140b9e commit 7de63ec

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

tests/codegen/transmute-scalar.rs renamed to tests/codegen/transmute-scalar-generic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ add-core-stubs
22
//@ compile-flags: -C opt-level=0 -C no-prepopulate-passes
3+
//@ ignore-riscv64
34

45
#![crate_type = "lib"]
56
#![feature(no_core, repr_simd, arm_target_feature, mips_target_feature, s390x_target_feature)]
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//@ add-core-stubs
2+
//@ compile-flags: -C opt-level=0 -C no-prepopulate-passes
3+
//@only-riscv64
4+
5+
#![crate_type = "lib"]
6+
#![feature(no_core, repr_simd, arm_target_feature, mips_target_feature, s390x_target_feature)]
7+
#![no_core]
8+
#![feature(riscv_target_feature)]
9+
extern crate minicore;
10+
11+
use minicore::*;
12+
13+
// With opaque ptrs in LLVM, `transmute` can load/store any `alloca` as any type,
14+
// without needing to pointercast, and SRoA will turn that into a `bitcast`.
15+
// Thus memory-to-memory transmutes don't need to generate them ourselves.
16+
17+
// However, `bitcast`s and `ptrtoint`s and `inttoptr`s are still worth doing when
18+
// that allows us to avoid the `alloca`s entirely; see `rvalue_creates_operand`.
19+
20+
// CHECK-LABEL: define{{.*}}i32 @f32_to_bits(float %x)
21+
// CHECK: %_0 = bitcast float %x to i32
22+
// CHECK-NEXT: ret i32 %_0
23+
#[no_mangle]
24+
pub fn f32_to_bits(x: f32) -> u32 {
25+
unsafe { mem::transmute(x) }
26+
}
27+
28+
// CHECK-LABEL: define{{.*}}i8 @bool_to_byte(i1 zeroext %b)
29+
// CHECK: %_0 = zext i1 %b to i8
30+
// CHECK-NEXT: ret i8 %_0
31+
#[no_mangle]
32+
pub fn bool_to_byte(b: bool) -> u8 {
33+
unsafe { mem::transmute(b) }
34+
}
35+
36+
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8{{.*}} %byte)
37+
// CHECK: %_0 = trunc{{( nuw)?}} i8 %byte to i1
38+
// CHECK-NEXT: ret i1 %_0
39+
#[no_mangle]
40+
pub unsafe fn byte_to_bool(byte: u8) -> bool {
41+
mem::transmute(byte)
42+
}
43+
44+
// CHECK-LABEL: define{{.*}}ptr @ptr_to_ptr(ptr %p)
45+
// CHECK: ret ptr %p
46+
#[no_mangle]
47+
pub fn ptr_to_ptr(p: *mut u16) -> *mut u8 {
48+
unsafe { mem::transmute(p) }
49+
}
50+
51+
// CHECK: define{{.*}}[[USIZE:i[0-9]+]] @ptr_to_int(ptr %p)
52+
// CHECK: %_0 = ptrtoint ptr %p to [[USIZE]]
53+
// CHECK-NEXT: ret [[USIZE]] %_0
54+
#[no_mangle]
55+
pub fn ptr_to_int(p: *mut u16) -> usize {
56+
unsafe { mem::transmute(p) }
57+
}
58+
59+
// CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i)
60+
// CHECK: %_0 = getelementptr i8, ptr null, [[USIZE]] %i
61+
// CHECK-NEXT: ret ptr %_0
62+
#[no_mangle]
63+
pub fn int_to_ptr(i: usize) -> *mut u16 {
64+
unsafe { mem::transmute(i) }
65+
}
66+
67+
// This is the one case where signedness matters to transmuting:
68+
// the LLVM type is `i8` here because of `repr(i8)`,
69+
// whereas below with the `repr(u8)` it's `i1` in LLVM instead.
70+
#[repr(i8)]
71+
pub enum FakeBoolSigned {
72+
False = 0,
73+
True = 1,
74+
}
75+
76+
// CHECK-LABEL: define{{.*}}i8 @bool_to_fake_bool_signed(i1 zeroext %b)
77+
// CHECK: %_0 = zext i1 %b to i8
78+
// CHECK-NEXT: ret i8 %_0
79+
#[no_mangle]
80+
pub fn bool_to_fake_bool_signed(b: bool) -> FakeBoolSigned {
81+
unsafe { mem::transmute(b) }
82+
}
83+
84+
// CHECK-LABEL: define{{.*}}i1 @fake_bool_signed_to_bool(i8 signext %b)
85+
// CHECK: %_0 = trunc nuw i8 %b to i1
86+
// CHECK-NEXT: ret i1 %_0
87+
#[no_mangle]
88+
pub fn fake_bool_signed_to_bool(b: FakeBoolSigned) -> bool {
89+
unsafe { mem::transmute(b) }
90+
}
91+
92+
#[repr(u8)]
93+
pub enum FakeBoolUnsigned {
94+
False = 0,
95+
True = 1,
96+
}
97+
98+
// CHECK-LABEL: define{{.*}}i1 @bool_to_fake_bool_unsigned(i1 zeroext %b)
99+
// CHECK: ret i1 %b
100+
#[no_mangle]
101+
pub fn bool_to_fake_bool_unsigned(b: bool) -> FakeBoolUnsigned {
102+
unsafe { mem::transmute(b) }
103+
}
104+
105+
// CHECK-LABEL: define{{.*}}i1 @fake_bool_unsigned_to_bool(i1 zeroext %b)
106+
// CHECK: ret i1 %b
107+
#[no_mangle]
108+
pub fn fake_bool_unsigned_to_bool(b: FakeBoolUnsigned) -> bool {
109+
unsafe { mem::transmute(b) }
110+
}
111+
112+
#[repr(simd)]
113+
struct S([i64; 1]);
114+
115+
// CHECK-LABEL: define{{.*}}i64 @single_element_simd_to_scalar(i64 %{{.*}})
116+
// CHECK-NEXT: start:
117+
// CHECK-NEXT: %[[RET:.+]] = alloca [8 x i8]
118+
// CHECK: store <1 x i64> %[[TEMP:.+]], ptr %[[RET]]
119+
// CHECK: %[[TEMP:.+]] = load i64, ptr %[[RET]]
120+
// CHECK: ret i64 %[[TEMP]]
121+
#[no_mangle]
122+
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
123+
pub extern "C" fn single_element_simd_to_scalar(b: S) -> i64 {
124+
unsafe { mem::transmute(b) }
125+
}
126+
127+
// CHECK-LABEL: define{{.*}}i64 @scalar_to_single_element_simd(i64 %b)
128+
// CHECK-NEXT: start:
129+
// CHECK-NEXT: %[[RET:.+]] = alloca [8 x i8]
130+
// CHECK-NEXT: store i64 %b, ptr %[[RET]]
131+
// CHECK-NEXT: %[[TEMP:.+]] = load i64, ptr %[[RET]]
132+
// CHECK-NEXT: ret i64 %[[TEMP]]
133+
#[no_mangle]
134+
#[cfg_attr(target_arch = "riscv64", target_feature(enable = "v"))]
135+
pub extern "C" fn scalar_to_single_element_simd(b: i64) -> S {
136+
unsafe { mem::transmute(b) }
137+
}

0 commit comments

Comments
 (0)