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