]> git.lizzy.rs Git - rust.git/blob - src/test/ui/simd/intrinsic/generic-cast-pass.rs
Auto merge of #95454 - randomicon00:fix95444, r=wesleywiser
[rust.git] / src / test / ui / simd / intrinsic / generic-cast-pass.rs
1 // run-pass
2 #![allow(unused_must_use)]
3 // ignore-emscripten FIXME(#45351) hits an LLVM assert
4
5 #![feature(repr_simd, platform_intrinsics, concat_idents, test)]
6 #![allow(non_camel_case_types)]
7
8 extern crate test;
9
10 #[repr(simd)]
11 #[derive(PartialEq, Debug)]
12 struct i32x4(i32, i32, i32, i32);
13 #[repr(simd)]
14 #[derive(PartialEq, Debug)]
15 struct i8x4(i8, i8, i8, i8);
16
17 #[repr(simd)]
18 #[derive(PartialEq, Debug)]
19 struct u32x4(u32, u32, u32, u32);
20 #[repr(simd)]
21 #[derive(PartialEq, Debug)]
22 struct u8x4(u8, u8, u8, u8);
23
24 #[repr(simd)]
25 #[derive(PartialEq, Debug)]
26 struct f32x4(f32, f32, f32, f32);
27
28 #[repr(simd)]
29 #[derive(PartialEq, Debug)]
30 struct f64x4(f64, f64, f64, f64);
31
32
33 extern "platform-intrinsic" {
34     fn simd_cast<T, U>(x: T) -> U;
35 }
36
37 const A: i32 = -1234567;
38 const B: i32 = 12345678;
39 const C: i32 = -123456789;
40 const D: i32 = 1234567890;
41
42 trait Foo {
43     fn is_float() -> bool { false }
44     fn in_range(x: i32) -> bool;
45 }
46 impl Foo for i32 {
47     fn in_range(_: i32) -> bool { true }
48 }
49 impl Foo for i8 {
50     fn in_range(x: i32) -> bool { -128 <= x && x < 128 }
51 }
52 impl Foo for u32 {
53     fn in_range(x: i32) -> bool { 0 <= x }
54 }
55 impl Foo for u8 {
56     fn in_range(x: i32) -> bool { 0 <= x && x < 128 }
57 }
58 impl Foo for f32 {
59     fn is_float() -> bool { true }
60     fn in_range(_: i32) -> bool { true }
61 }
62 impl Foo for f64 {
63     fn is_float() -> bool { true }
64     fn in_range(_: i32) -> bool { true }
65 }
66
67 fn main() {
68     macro_rules! test {
69         ($from: ident, $to: ident) => {{
70             // force the casts to actually happen, or else LLVM/rustc
71             // may fold them and get slightly different results.
72             let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from));
73             // the SIMD vectors are all FOOx4, so we can concat_idents
74             // so we don't have to pass in the extra args to the macro
75             let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d));
76             let mut to = concat_idents!($to, x4)(a as $to,
77                                                  b as $to,
78                                                  c as $to,
79                                                  d as $to);
80             // assist type inference, it needs to know what `from` is
81             // for the `if` statements.
82             to == from;
83
84             // there are platform differences for some out of range
85             // casts, so we just normalize such things: it's OK for
86             // "invalid" calculations to result in nonsense answers.
87             // (e.g., negative float to unsigned integer goes through a
88             // library routine on the default i686 platforms, and the
89             // implementation of that routine differs on e.g., Linux
90             // vs. macOS, resulting in different answers.)
91             if $from::is_float() {
92                 if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; }
93                 if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; }
94                 if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; }
95                 if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; }
96             }
97
98             assert!(to == from,
99                     "{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to),
100                     from, to);
101         }}
102     }
103     macro_rules! tests {
104         (: $($to: ident),*) => { () };
105         // repeating the list twice is easier than writing a cartesian
106         // product macro
107         ($from: ident $(, $from_: ident)*: $($to: ident),*) => {
108             fn $from() { unsafe { $( test!($from, $to); )* } }
109             tests!($($from_),*: $($to),*)
110         };
111         ($($types: ident),*) => {{
112             tests!($($types),* : $($types),*);
113             $($types();)*
114         }}
115     }
116
117     // test various combinations, including truncation,
118     // signed/unsigned extension, and floating point casts.
119     tests!(i32, i8, u32, u8, f32);
120     tests!(i32, u32, f32, f64)
121 }