1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
// This test check that even if we mixup target feature of function with homogenous floats,
// the abi is sound and still produce the right answer.
//
// This is basically the same test as tests/ui/simd/target-feature-mixup.rs but for floats and
// without #[repr(simd)]
//@ run-pass
//@ ignore-wasm32 no processes
//@ ignore-sgx no processes
#![feature(avx512_target_feature)]
#![allow(overflowing_literals)]
#![allow(unused_variables)]
use std::process::{Command, ExitStatus};
use std::env;
fn main() {
if let Some(level) = env::args().nth(1) {
return test::main(&level)
}
match std::env::var("TARGET") {
Ok(s) => {
// Skip this tests on i586-unknown-linux-gnu where sse2 is disabled
if s.contains("i586") {
return
}
}
Err(_) => return,
}
let me = env::current_exe().unwrap();
for level in ["sse", "avx", "avx512"].iter() {
let status = Command::new(&me).arg(level).status().unwrap();
if status.success() {
println!("success with {}", level);
continue
}
// We don't actually know if our computer has the requisite target features
// for the test below. Testing for that will get added to libstd later so
// for now just assume sigill means this is a machine that can't run this test.
if is_sigill(status) {
println!("sigill with {}, assuming spurious", level);
continue
}
panic!("invalid status at {}: {}", level, status);
}
}
#[cfg(unix)]
fn is_sigill(status: ExitStatus) -> bool {
use std::os::unix::prelude::*;
status.signal() == Some(4)
}
#[cfg(windows)]
fn is_sigill(status: ExitStatus) -> bool {
status.code() == Some(0xc000001d)
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[allow(nonstandard_style)]
mod test {
#[derive(PartialEq, Debug, Clone, Copy)]
struct f32x2([f32; 2]);
#[derive(PartialEq, Debug, Clone, Copy)]
struct f32x4([f32; 4]);
#[derive(PartialEq, Debug, Clone, Copy)]
struct f32x8([f32; 8]);
pub fn main(level: &str) {
unsafe {
main_normal(level);
main_sse(level);
if level == "sse" {
return
}
main_avx(level);
if level == "avx" {
return
}
main_avx512(level);
}
}
macro_rules! mains {
($(
$(#[$attr:meta])*
unsafe fn $main:ident(level: &str) {
...
}
)*) => ($(
$(#[$attr])*
unsafe fn $main(level: &str) {
let m128 = f32x2([1., 2.]);
let m256 = f32x4([3., 4., 5., 6.]);
let m512 = f32x8([7., 8., 9., 10., 11., 12., 13., 14.]);
assert_eq!(id_sse_128(m128), m128);
assert_eq!(id_sse_256(m256), m256);
assert_eq!(id_sse_512(m512), m512);
if level == "sse" {
return
}
assert_eq!(id_avx_128(m128), m128);
assert_eq!(id_avx_256(m256), m256);
assert_eq!(id_avx_512(m512), m512);
if level == "avx" {
return
}
assert_eq!(id_avx512_128(m128), m128);
assert_eq!(id_avx512_256(m256), m256);
assert_eq!(id_avx512_512(m512), m512);
}
)*)
}
mains! {
unsafe fn main_normal(level: &str) { ... }
#[target_feature(enable = "sse2")]
unsafe fn main_sse(level: &str) { ... }
#[target_feature(enable = "avx")]
unsafe fn main_avx(level: &str) { ... }
#[target_feature(enable = "avx512bw")]
unsafe fn main_avx512(level: &str) { ... }
}
#[target_feature(enable = "sse2")]
unsafe fn id_sse_128(a: f32x2) -> f32x2 {
assert_eq!(a, f32x2([1., 2.]));
a.clone()
}
#[target_feature(enable = "sse2")]
unsafe fn id_sse_256(a: f32x4) -> f32x4 {
assert_eq!(a, f32x4([3., 4., 5., 6.]));
a.clone()
}
#[target_feature(enable = "sse2")]
unsafe fn id_sse_512(a: f32x8) -> f32x8 {
assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_128(a: f32x2) -> f32x2 {
assert_eq!(a, f32x2([1., 2.]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_256(a: f32x4) -> f32x4 {
assert_eq!(a, f32x4([3., 4., 5., 6.]));
a.clone()
}
#[target_feature(enable = "avx")]
unsafe fn id_avx_512(a: f32x8) -> f32x8 {
assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_128(a: f32x2) -> f32x2 {
assert_eq!(a, f32x2([1., 2.]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_256(a: f32x4) -> f32x4 {
assert_eq!(a, f32x4([3., 4., 5., 6.]));
a.clone()
}
#[target_feature(enable = "avx512bw")]
unsafe fn id_avx512_512(a: f32x8) -> f32x8 {
assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.]));
a.clone()
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
mod test {
pub fn main(level: &str) {}
}
|