summary refs log tree commit diff
path: root/src/test/ui/simd
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 01:33:01 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 18:56:16 +0300
commit9be35f82c1abf2ecbab489bca9eca138ea648312 (patch)
tree69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/simd
parentca9faa52f5ada0054b1fa27d97aedf448afb059b (diff)
downloadrust-9be35f82c1abf2ecbab489bca9eca138ea648312.tar.gz
rust-9be35f82c1abf2ecbab489bca9eca138ea648312.zip
tests: Move run-pass tests without naming conflicts to ui
Diffstat (limited to 'src/test/ui/simd')
-rw-r--r--src/test/ui/simd/simd-generics.rs39
-rw-r--r--src/test/ui/simd/simd-intrinsic-float-math.rs103
-rw-r--r--src/test/ui/simd/simd-intrinsic-float-minmax.rs54
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs92
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs120
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-bitmask.rs61
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-cast.rs121
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-comparison.rs106
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-elements.rs125
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-gather.rs141
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-reduction.rs165
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-select.rs173
-rw-r--r--src/test/ui/simd/simd-size-align.rs96
-rw-r--r--src/test/ui/simd/simd-target-feature-mixup.rs185
-rw-r--r--src/test/ui/simd/simd-type.rs16
15 files changed, 1597 insertions, 0 deletions
diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/simd-generics.rs
new file mode 100644
index 00000000000..ab6caee9d7b
--- /dev/null
+++ b/src/test/ui/simd/simd-generics.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+
+
+#![feature(repr_simd, platform_intrinsics)]
+
+use std::ops;
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(f32, f32, f32, f32);
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(x: T, y: T) -> T;
+}
+
+fn add<T: ops::Add<Output=T>>(lhs: T, rhs: T) -> T {
+    lhs + rhs
+}
+
+impl ops::Add for f32x4 {
+    type Output = f32x4;
+
+    fn add(self, rhs: f32x4) -> f32x4 {
+        unsafe {simd_add(self, rhs)}
+    }
+}
+
+pub fn main() {
+    let lr = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32);
+
+    // lame-o
+    let f32x4(x, y, z, w) = add(lr, lr);
+    assert_eq!(x, 2.0f32);
+    assert_eq!(y, 4.0f32);
+    assert_eq!(z, 6.0f32);
+    assert_eq!(w, 8.0f32);
+}
diff --git a/src/test/ui/simd/simd-intrinsic-float-math.rs b/src/test/ui/simd/simd-intrinsic-float-math.rs
new file mode 100644
index 00000000000..220a59535ca
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-float-math.rs
@@ -0,0 +1,103 @@
+// run-pass
+// ignore-emscripten
+// ignore-android
+
+// FIXME: this test fails on arm-android because the NDK version 14 is too old.
+// It needs at least version 18. We disable it on all android build bots because
+// there is no way in compile-test to disable it for an (arch,os) pair.
+
+// Test that the simd floating-point math intrinsics produce correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fsqrt<T>(x: T) -> T;
+    fn simd_fabs<T>(x: T) -> T;
+    fn simd_fsin<T>(x: T) -> T;
+    fn simd_fcos<T>(x: T) -> T;
+    fn simd_ceil<T>(x: T) -> T;
+    fn simd_fexp<T>(x: T) -> T;
+    fn simd_fexp2<T>(x: T) -> T;
+    fn simd_floor<T>(x: T) -> T;
+    fn simd_fma<T>(x: T, y: T, z: T) -> T;
+    fn simd_flog<T>(x: T) -> T;
+    fn simd_flog10<T>(x: T) -> T;
+    fn simd_flog2<T>(x: T) -> T;
+    fn simd_fpow<T>(x: T, y: T) -> T;
+    fn simd_fpowi<T>(x: T, y: i32) -> T;
+}
+
+macro_rules! assert_approx_eq_f32 {
+    ($a:expr, $b:expr) => ({
+        let (a, b) = (&$a, &$b);
+        assert!((*a - *b).abs() < 1.0e-6,
+                "{} is not approximately equal to {}", *a, *b);
+    })
+}
+macro_rules! assert_approx_eq {
+    ($a:expr, $b:expr) => ({
+        let a = $a;
+        let b = $b;
+        assert_approx_eq_f32!(a.0, b.0);
+        assert_approx_eq_f32!(a.1, b.1);
+        assert_approx_eq_f32!(a.2, b.2);
+        assert_approx_eq_f32!(a.3, b.3);
+    })
+}
+
+fn main() {
+    let x = f32x4(1.0, 1.0, 1.0, 1.0);
+    let y = f32x4(-1.0, -1.0, -1.0, -1.0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    let h = f32x4(0.5, 0.5, 0.5, 0.5);
+
+    unsafe {
+        let r = simd_fabs(y);
+        assert_approx_eq!(x, r);
+
+        let r = simd_fcos(z);
+        assert_approx_eq!(x, r);
+
+        let r = simd_ceil(h);
+        assert_approx_eq!(x, r);
+
+        let r = simd_fexp(z);
+        assert_approx_eq!(x, r);
+
+        let r = simd_fexp2(z);
+        assert_approx_eq!(x, r);
+
+        let r = simd_floor(h);
+        assert_approx_eq!(z, r);
+
+        let r = simd_fma(x, h, h);
+        assert_approx_eq!(x, r);
+
+        let r = simd_fsqrt(x);
+        assert_approx_eq!(x, r);
+
+        let r = simd_flog(x);
+        assert_approx_eq!(z, r);
+
+        let r = simd_flog2(x);
+        assert_approx_eq!(z, r);
+
+        let r = simd_flog10(x);
+        assert_approx_eq!(z, r);
+
+        let r = simd_fpow(h, x);
+        assert_approx_eq!(h, r);
+
+        let r = simd_fpowi(h, 1);
+        assert_approx_eq!(h, r);
+
+        let r = simd_fsin(z);
+        assert_approx_eq!(z, r);
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-float-minmax.rs b/src/test/ui/simd/simd-intrinsic-float-minmax.rs
new file mode 100644
index 00000000000..350bc434935
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-float-minmax.rs
@@ -0,0 +1,54 @@
+// run-pass
+// ignore-emscripten
+// min-llvm-version 7.0
+// error-pattern: panicked
+
+// Test that the simd_f{min,max} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_fmin<T>(x: T, y: T) -> T;
+    fn simd_fmax<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let x = f32x4(1.0, 2.0, 3.0, 4.0);
+    let y = f32x4(2.0, 1.0, 4.0, 3.0);
+
+    #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+    let nan = ::std::f32::NAN;
+    // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
+    // See https://github.com/rust-lang/rust/issues/52746.
+    #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+    let nan = f32::from_bits(::std::f32::NAN.to_bits() - 1);
+
+    let n = f32x4(nan, nan, nan, nan);
+
+    unsafe {
+        let min0 = simd_fmin(x, y);
+        let min1 = simd_fmin(y, x);
+        assert_eq!(min0, min1);
+        let e = f32x4(1.0, 1.0, 3.0, 3.0);
+        assert_eq!(min0, e);
+        let minn = simd_fmin(x, n);
+        assert_eq!(minn, x);
+        let minn = simd_fmin(y, n);
+        assert_eq!(minn, y);
+
+        let max0 = simd_fmax(x, y);
+        let max1 = simd_fmax(y, x);
+        assert_eq!(max0, max1);
+        let e = f32x4(2.0, 2.0, 4.0, 4.0);
+        assert_eq!(max0, e);
+        let maxn = simd_fmax(x, n);
+        assert_eq!(maxn, x);
+        let maxn = simd_fmax(y, n);
+        assert_eq!(maxn, y);
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
new file mode 100644
index 00000000000..b2ddcf023eb
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -0,0 +1,92 @@
+// run-pass
+// ignore-emscripten
+// min-llvm-version 8.0
+
+#![allow(non_camel_case_types)]
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+extern "platform-intrinsic" {
+    fn simd_saturating_add<T>(x: T, y: T) -> T;
+    fn simd_saturating_sub<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    // unsigned
+    {
+        const M: u32 = u32::max_value();
+
+        let a = u32x4(1, 2, 3, 4);
+        let b = u32x4(2, 4, 6, 8);
+        let m = u32x4(M, M, M, M);
+        let m1 = u32x4(M - 1, M - 1, M - 1, M - 1);
+        let z = u32x4(0, 0, 0, 0);
+
+        unsafe {
+            assert_eq!(simd_saturating_add(z, z), z);
+            assert_eq!(simd_saturating_add(z, a), a);
+            assert_eq!(simd_saturating_add(b, z), b);
+            assert_eq!(simd_saturating_add(a, a), b);
+            assert_eq!(simd_saturating_add(a, m), m);
+            assert_eq!(simd_saturating_add(m, b), m);
+            assert_eq!(simd_saturating_add(m1, a), m);
+
+            assert_eq!(simd_saturating_sub(b, z), b);
+            assert_eq!(simd_saturating_sub(b, a), a);
+            assert_eq!(simd_saturating_sub(a, a), z);
+            assert_eq!(simd_saturating_sub(a, b), z);
+            assert_eq!(simd_saturating_sub(a, m1), z);
+            assert_eq!(simd_saturating_sub(b, m1), z);
+        }
+    }
+
+    // signed
+    {
+        const MIN: i32 = i32::min_value();
+        const MAX: i32 = i32::max_value();
+
+        let a = i32x4(1, 2, 3, 4);
+        let b = i32x4(2, 4, 6, 8);
+        let c = i32x4(-1, -2, -3, -4);
+        let d = i32x4(-2, -4, -6, -8);
+
+        let max = i32x4(MAX, MAX, MAX, MAX);
+        let max1 = i32x4(MAX - 1, MAX - 1, MAX - 1, MAX - 1);
+        let min = i32x4(MIN, MIN, MIN, MIN);
+        let min1 = i32x4(MIN + 1, MIN + 1, MIN + 1, MIN + 1);
+
+        let z = i32x4(0, 0, 0, 0);
+
+        unsafe {
+            assert_eq!(simd_saturating_add(z, z), z);
+            assert_eq!(simd_saturating_add(z, a), a);
+            assert_eq!(simd_saturating_add(b, z), b);
+            assert_eq!(simd_saturating_add(a, a), b);
+            assert_eq!(simd_saturating_add(a, max), max);
+            assert_eq!(simd_saturating_add(max, b), max);
+            assert_eq!(simd_saturating_add(max1, a), max);
+            assert_eq!(simd_saturating_add(min1, z), min1);
+            assert_eq!(simd_saturating_add(min, z), min);
+            assert_eq!(simd_saturating_add(min1, c), min);
+            assert_eq!(simd_saturating_add(min, c), min);
+            assert_eq!(simd_saturating_add(min1, d), min);
+            assert_eq!(simd_saturating_add(min, d), min);
+
+            assert_eq!(simd_saturating_sub(b, z), b);
+            assert_eq!(simd_saturating_sub(b, a), a);
+            assert_eq!(simd_saturating_sub(a, a), z);
+            assert_eq!(simd_saturating_sub(a, b), c);
+            assert_eq!(simd_saturating_sub(z, max), min1);
+            assert_eq!(simd_saturating_sub(min1, z), min1);
+            assert_eq!(simd_saturating_sub(min1, a), min);
+            assert_eq!(simd_saturating_sub(min1, b), min);
+        }
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs
new file mode 100644
index 00000000000..b67c0ad1eb2
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs
@@ -0,0 +1,120 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+macro_rules! all_eq {
+    ($a: expr, $b: expr) => {{
+        let a = $a;
+        let b = $b;
+        assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3);
+    }}
+}
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(x: T, y: T) -> T;
+    fn simd_sub<T>(x: T, y: T) -> T;
+    fn simd_mul<T>(x: T, y: T) -> T;
+    fn simd_div<T>(x: T, y: T) -> T;
+    fn simd_rem<T>(x: T, y: T) -> T;
+    fn simd_shl<T>(x: T, y: T) -> T;
+    fn simd_shr<T>(x: T, y: T) -> T;
+    fn simd_and<T>(x: T, y: T) -> T;
+    fn simd_or<T>(x: T, y: T) -> T;
+    fn simd_xor<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let x1 = i32x4(1, 2, 3, 4);
+    let y1 = u32x4(1, 2, 3, 4);
+    let z1 = f32x4(1.0, 2.0, 3.0, 4.0);
+    let x2 = i32x4(2, 3, 4, 5);
+    let y2 = u32x4(2, 3, 4, 5);
+    let z2 = f32x4(2.0, 3.0, 4.0, 5.0);
+
+    unsafe {
+        all_eq!(simd_add(x1, x2), i32x4(3, 5, 7, 9));
+        all_eq!(simd_add(x2, x1), i32x4(3, 5, 7, 9));
+        all_eq!(simd_add(y1, y2), u32x4(3, 5, 7, 9));
+        all_eq!(simd_add(y2, y1), u32x4(3, 5, 7, 9));
+        all_eq!(simd_add(z1, z2), f32x4(3.0, 5.0, 7.0, 9.0));
+        all_eq!(simd_add(z2, z1), f32x4(3.0, 5.0, 7.0, 9.0));
+
+        all_eq!(simd_mul(x1, x2), i32x4(2, 6, 12, 20));
+        all_eq!(simd_mul(x2, x1), i32x4(2, 6, 12, 20));
+        all_eq!(simd_mul(y1, y2), u32x4(2, 6, 12, 20));
+        all_eq!(simd_mul(y2, y1), u32x4(2, 6, 12, 20));
+        all_eq!(simd_mul(z1, z2), f32x4(2.0, 6.0, 12.0, 20.0));
+        all_eq!(simd_mul(z2, z1), f32x4(2.0, 6.0, 12.0, 20.0));
+
+        all_eq!(simd_sub(x2, x1), i32x4(1, 1, 1, 1));
+        all_eq!(simd_sub(x1, x2), i32x4(-1, -1, -1, -1));
+        all_eq!(simd_sub(y2, y1), u32x4(1, 1, 1, 1));
+        all_eq!(simd_sub(y1, y2), u32x4(!0, !0, !0, !0));
+        all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0));
+        all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0));
+
+        all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1));
+        all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1);
+        all_eq!(simd_div(y1, y1), u32x4(1, 1, 1, 1));
+        all_eq!(simd_div(u32x4(2, 4, 6, 8), u32x4(2, 2, 2, 2)), y1);
+        all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0));
+        all_eq!(simd_div(z1, z2), f32x4(1.0/2.0, 2.0/3.0, 3.0/4.0, 4.0/5.0));
+        all_eq!(simd_div(z2, z1), f32x4(2.0/1.0, 3.0/2.0, 4.0/3.0, 5.0/4.0));
+
+        all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0));
+        all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1));
+        all_eq!(simd_rem(y1, y1), u32x4(0, 0, 0, 0));
+        all_eq!(simd_rem(y2, y1), u32x4(0, 1, 1, 1));
+        all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0));
+        all_eq!(simd_rem(z1, z2), z1);
+        all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0));
+
+        all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5));
+        all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4));
+        all_eq!(simd_shl(y1, y2), u32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5));
+        all_eq!(simd_shl(y2, y1), u32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4));
+
+        // test right-shift by assuming left-shift is correct
+        all_eq!(simd_shr(simd_shl(x1, x2), x2), x1);
+        all_eq!(simd_shr(simd_shl(x2, x1), x1), x2);
+        all_eq!(simd_shr(simd_shl(y1, y2), y2), y1);
+        all_eq!(simd_shr(simd_shl(y2, y1), y1), y2);
+
+        // ensure we get logical vs. arithmetic shifts correct
+        let (a, b, c, d) = (-12, -123, -1234, -12345);
+        all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4));
+        all_eq!(simd_shr(u32x4(a as u32, b as u32, c as u32, d as u32), y1),
+                u32x4((a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4));
+
+        all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4));
+        all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4));
+        all_eq!(simd_and(y1, y2), u32x4(0, 2, 0, 4));
+        all_eq!(simd_and(y2, y1), u32x4(0, 2, 0, 4));
+
+        all_eq!(simd_or(x1, x2), i32x4(3, 3, 7, 5));
+        all_eq!(simd_or(x2, x1), i32x4(3, 3, 7, 5));
+        all_eq!(simd_or(y1, y2), u32x4(3, 3, 7, 5));
+        all_eq!(simd_or(y2, y1), u32x4(3, 3, 7, 5));
+
+        all_eq!(simd_xor(x1, x2), i32x4(3, 1, 7, 1));
+        all_eq!(simd_xor(x2, x1), i32x4(3, 1, 7, 1));
+        all_eq!(simd_xor(y1, y2), u32x4(3, 1, 7, 1));
+        all_eq!(simd_xor(y2, y1), u32x4(3, 1, 7, 1));
+
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 00000000000..b28f742a92e
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs
@@ -0,0 +1,61 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// ignore-emscripten
+
+// Test that the simd_bitmask intrinsic produces correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u8x4(pub u8, pub u8, pub u8, pub u8);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct Tx4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let z = u32x4(0, 0, 0, 0);
+    let ez = 0_u8;
+
+    let o = u32x4(!0, !0, !0, !0);
+    let eo = 0b_1111_u8;
+
+    let m0 = u32x4(!0, 0, !0, 0);
+    let e0 = 0b_0000_0101_u8;
+
+    // Check that the MSB is extracted:
+    let m = u8x4(0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111);
+    let e = 0b_1101;
+
+    // Check usize / isize
+    let msize: Tx4<usize> = Tx4(usize::max_value(), 0, usize::max_value(), usize::max_value());
+
+    unsafe {
+        let r: u8 = simd_bitmask(z);
+        assert_eq!(r, ez);
+
+        let r: u8 = simd_bitmask(o);
+        assert_eq!(r, eo);
+
+        let r: u8 = simd_bitmask(m0);
+        assert_eq!(r, e0);
+
+        let r: u8 = simd_bitmask(m);
+        assert_eq!(r, e);
+
+        let r: u8 = simd_bitmask(msize);
+        assert_eq!(r, e);
+
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-cast.rs b/src/test/ui/simd/simd-intrinsic-generic-cast.rs
new file mode 100644
index 00000000000..15f232e2c0f
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-cast.rs
@@ -0,0 +1,121 @@
+// run-pass
+#![allow(unused_must_use)]
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
+#![feature(repr_simd, platform_intrinsics, concat_idents, test)]
+#![allow(non_camel_case_types)]
+
+extern crate test;
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct i8x4(i8, i8, i8, i8);
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct u32x4(u32, u32, u32, u32);
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct u8x4(u8, u8, u8, u8);
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct f32x4(f32, f32, f32, f32);
+
+#[repr(simd)]
+#[derive(PartialEq, Debug)]
+struct f64x4(f64, f64, f64, f64);
+
+
+extern "platform-intrinsic" {
+    fn simd_cast<T, U>(x: T) -> U;
+}
+
+const A: i32 = -1234567;
+const B: i32 = 12345678;
+const C: i32 = -123456789;
+const D: i32 = 1234567890;
+
+trait Foo {
+    fn is_float() -> bool { false }
+    fn in_range(x: i32) -> bool;
+}
+impl Foo for i32 {
+    fn in_range(_: i32) -> bool { true }
+}
+impl Foo for i8 {
+    fn in_range(x: i32) -> bool { -128 <= x && x < 128 }
+}
+impl Foo for u32 {
+    fn in_range(x: i32) -> bool { 0 <= x }
+}
+impl Foo for u8 {
+    fn in_range(x: i32) -> bool { 0 <= x && x < 128 }
+}
+impl Foo for f32 {
+    fn is_float() -> bool { true }
+    fn in_range(_: i32) -> bool { true }
+}
+impl Foo for f64 {
+    fn is_float() -> bool { true }
+    fn in_range(_: i32) -> bool { true }
+}
+
+fn main() {
+    macro_rules! test {
+        ($from: ident, $to: ident) => {{
+            // force the casts to actually happen, or else LLVM/rustc
+            // may fold them and get slightly different results.
+            let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from));
+            // the SIMD vectors are all FOOx4, so we can concat_idents
+            // so we don't have to pass in the extra args to the macro
+            let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d));
+            let mut to = concat_idents!($to, x4)(a as $to,
+                                                 b as $to,
+                                                 c as $to,
+                                                 d as $to);
+            // assist type inference, it needs to know what `from` is
+            // for the `if` statements.
+            to == from;
+
+            // there are platform differences for some out of range
+            // casts, so we just normalize such things: it's OK for
+            // "invalid" calculations to result in nonsense answers.
+            // (e.g., negative float to unsigned integer goes through a
+            // library routine on the default i686 platforms, and the
+            // implementation of that routine differs on e.g., Linux
+            // vs. macOS, resulting in different answers.)
+            if $from::is_float() {
+                if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; }
+                if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; }
+                if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; }
+                if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; }
+            }
+
+            assert!(to == from,
+                    "{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to),
+                    from, to);
+        }}
+    }
+    macro_rules! tests {
+        (: $($to: ident),*) => { () };
+        // repeating the list twice is easier than writing a cartesian
+        // product macro
+        ($from: ident $(, $from_: ident)*: $($to: ident),*) => {
+            fn $from() { unsafe { $( test!($from, $to); )* } }
+            tests!($($from_),*: $($to),*)
+        };
+        ($($types: ident),*) => {{
+            tests!($($types),* : $($types),*);
+            $($types();)*
+        }}
+    }
+
+    // test various combinations, including truncation,
+    // signed/unsigned extension, and floating point casts.
+    tests!(i32, i8, u32, u8, f32);
+    tests!(i32, u32, f32, f64)
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd/simd-intrinsic-generic-comparison.rs
new file mode 100644
index 00000000000..2b593e1c9b8
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-comparison.rs
@@ -0,0 +1,106 @@
+// run-pass
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
+#![feature(repr_simd, platform_intrinsics, concat_idents)]
+#![allow(non_camel_case_types)]
+
+use std::f32::NAN;
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+    fn simd_eq<T, U>(x: T, y: T) -> U;
+    fn simd_ne<T, U>(x: T, y: T) -> U;
+    fn simd_lt<T, U>(x: T, y: T) -> U;
+    fn simd_le<T, U>(x: T, y: T) -> U;
+    fn simd_gt<T, U>(x: T, y: T) -> U;
+    fn simd_ge<T, U>(x: T, y: T) -> U;
+}
+
+macro_rules! cmp {
+    ($method: ident($lhs: expr, $rhs: expr)) => {{
+        let lhs = $lhs;
+        let rhs = $rhs;
+        let e: u32x4 = concat_idents!(simd_, $method)($lhs, $rhs);
+        // assume the scalar version is correct/the behaviour we want.
+        assert!((e.0 != 0) == lhs.0 .$method(&rhs.0));
+        assert!((e.1 != 0) == lhs.1 .$method(&rhs.1));
+        assert!((e.2 != 0) == lhs.2 .$method(&rhs.2));
+        assert!((e.3 != 0) == lhs.3 .$method(&rhs.3));
+    }}
+}
+macro_rules! tests {
+    ($($lhs: ident, $rhs: ident;)*) => {{
+        $(
+            (|| {
+                cmp!(eq($lhs, $rhs));
+                cmp!(ne($lhs, $rhs));
+
+                // test both directions
+                cmp!(lt($lhs, $rhs));
+                cmp!(lt($rhs, $lhs));
+
+                cmp!(le($lhs, $rhs));
+                cmp!(le($rhs, $lhs));
+
+                cmp!(gt($lhs, $rhs));
+                cmp!(gt($rhs, $lhs));
+
+                cmp!(ge($lhs, $rhs));
+                cmp!(ge($rhs, $lhs));
+            })();
+            )*
+    }}
+}
+fn main() {
+    // 13 vs. -100 tests that we get signed vs. unsigned comparisons
+    // correct (i32: 13 > -100, u32: 13 < -100).    let i1 = i32x4(10, -11, 12, 13);
+    let i1 = i32x4(10, -11, 12, 13);
+    let i2 = i32x4(5, -5, 20, -100);
+    let i3 = i32x4(10, -11, 20, -100);
+
+    let u1 = u32x4(10, !11+1, 12, 13);
+    let u2 = u32x4(5, !5+1, 20, !100+1);
+    let u3 = u32x4(10, !11+1, 20, !100+1);
+
+    let f1 = f32x4(10.0, -11.0, 12.0, 13.0);
+    let f2 = f32x4(5.0, -5.0, 20.0, -100.0);
+    let f3 = f32x4(10.0, -11.0, 20.0, -100.0);
+
+    unsafe {
+        tests! {
+            i1, i1;
+            u1, u1;
+            f1, f1;
+
+            i1, i2;
+            u1, u2;
+            f1, f2;
+
+            i1, i3;
+            u1, u3;
+            f1, f3;
+        }
+    }
+
+    // NAN comparisons are special:
+    // -11 (*)    13
+    // -5        -100 (*)
+    let f4 = f32x4(NAN, f1.1, NAN, f2.3);
+
+    unsafe {
+        tests! {
+            f1, f4;
+            f2, f4;
+            f4, f4;
+        }
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/simd-intrinsic-generic-elements.rs
new file mode 100644
index 00000000000..ea3d4b18944
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-elements.rs
@@ -0,0 +1,125 @@
+// run-pass
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[allow(non_camel_case_types)]
+struct i32x2(i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[allow(non_camel_case_types)]
+struct i32x3(i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[allow(non_camel_case_types)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[allow(non_camel_case_types)]
+struct i32x8(i32, i32, i32, i32,
+             i32, i32, i32, i32);
+
+extern "platform-intrinsic" {
+    fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
+    fn simd_extract<T, E>(x: T, idx: u32) -> E;
+
+    fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
+    fn simd_shuffle3<T, U>(x: T, y: T, idx: [u32; 3]) -> U;
+    fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
+    fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
+}
+
+macro_rules! all_eq {
+    ($a: expr, $b: expr) => {{
+        let a = $a;
+        let b = $b;
+        // type inference works better with the concrete type on the
+        // left, but humans work better with the expected on the
+        // right.
+        assert!(b == a,
+                "{:?} != {:?}", a, b);
+    }}
+}
+
+fn main() {
+    let x2 = i32x2(20, 21);
+    let x3 = i32x3(30, 31, 32);
+    let x4 = i32x4(40, 41, 42, 43);
+    let x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87);
+    unsafe {
+        all_eq!(simd_insert(x2, 0, 100), i32x2(100, 21));
+        all_eq!(simd_insert(x2, 1, 100), i32x2(20, 100));
+
+        all_eq!(simd_insert(x3, 0, 100), i32x3(100, 31, 32));
+        all_eq!(simd_insert(x3, 1, 100), i32x3(30, 100, 32));
+        all_eq!(simd_insert(x3, 2, 100), i32x3(30, 31, 100));
+
+        all_eq!(simd_insert(x4, 0, 100), i32x4(100, 41, 42, 43));
+        all_eq!(simd_insert(x4, 1, 100), i32x4(40, 100, 42, 43));
+        all_eq!(simd_insert(x4, 2, 100), i32x4(40, 41, 100, 43));
+        all_eq!(simd_insert(x4, 3, 100), i32x4(40, 41, 42, 100));
+
+        all_eq!(simd_insert(x8, 0, 100), i32x8(100, 81, 82, 83, 84, 85, 86, 87));
+        all_eq!(simd_insert(x8, 1, 100), i32x8(80, 100, 82, 83, 84, 85, 86, 87));
+        all_eq!(simd_insert(x8, 2, 100), i32x8(80, 81, 100, 83, 84, 85, 86, 87));
+        all_eq!(simd_insert(x8, 3, 100), i32x8(80, 81, 82, 100, 84, 85, 86, 87));
+        all_eq!(simd_insert(x8, 4, 100), i32x8(80, 81, 82, 83, 100, 85, 86, 87));
+        all_eq!(simd_insert(x8, 5, 100), i32x8(80, 81, 82, 83, 84, 100, 86, 87));
+        all_eq!(simd_insert(x8, 6, 100), i32x8(80, 81, 82, 83, 84, 85, 100, 87));
+        all_eq!(simd_insert(x8, 7, 100), i32x8(80, 81, 82, 83, 84, 85, 86, 100));
+
+        all_eq!(simd_extract(x2, 0), 20);
+        all_eq!(simd_extract(x2, 1), 21);
+
+        all_eq!(simd_extract(x3, 0), 30);
+        all_eq!(simd_extract(x3, 1), 31);
+        all_eq!(simd_extract(x3, 2), 32);
+
+        all_eq!(simd_extract(x4, 0), 40);
+        all_eq!(simd_extract(x4, 1), 41);
+        all_eq!(simd_extract(x4, 2), 42);
+        all_eq!(simd_extract(x4, 3), 43);
+
+        all_eq!(simd_extract(x8, 0), 80);
+        all_eq!(simd_extract(x8, 1), 81);
+        all_eq!(simd_extract(x8, 2), 82);
+        all_eq!(simd_extract(x8, 3), 83);
+        all_eq!(simd_extract(x8, 4), 84);
+        all_eq!(simd_extract(x8, 5), 85);
+        all_eq!(simd_extract(x8, 6), 86);
+        all_eq!(simd_extract(x8, 7), 87);
+    }
+
+    let y2 = i32x2(120, 121);
+    let y3 = i32x3(130, 131, 132);
+    let y4 = i32x4(140, 141, 142, 143);
+    let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187);
+    unsafe {
+        all_eq!(simd_shuffle2(x2, y2, [3, 0]), i32x2(121, 20));
+        all_eq!(simd_shuffle3(x2, y2, [3, 0, 1]), i32x3(121, 20, 21));
+        all_eq!(simd_shuffle4(x2, y2, [3, 0, 1, 2]), i32x4(121, 20, 21, 120));
+        all_eq!(simd_shuffle8(x2, y2, [3, 0, 1, 2, 1, 2, 3, 0]),
+                i32x8(121, 20, 21, 120, 21, 120, 121, 20));
+
+        all_eq!(simd_shuffle2(x3, y3, [4, 2]), i32x2(131, 32));
+        all_eq!(simd_shuffle3(x3, y3, [4, 2, 3]), i32x3(131, 32, 130));
+        all_eq!(simd_shuffle4(x3, y3, [4, 2, 3, 0]), i32x4(131, 32, 130, 30));
+        all_eq!(simd_shuffle8(x3, y3, [4, 2, 3, 0, 1, 5, 5, 1]),
+                i32x8(131, 32, 130, 30, 31, 132, 132, 31));
+
+        all_eq!(simd_shuffle2(x4, y4, [7, 2]), i32x2(143, 42));
+        all_eq!(simd_shuffle3(x4, y4, [7, 2, 5]), i32x3(143, 42, 141));
+        all_eq!(simd_shuffle4(x4, y4, [7, 2, 5, 0]), i32x4(143, 42, 141, 40));
+        all_eq!(simd_shuffle8(x4, y4, [7, 2, 5, 0, 3, 6, 4, 1]),
+                i32x8(143, 42, 141, 40, 43, 142, 140, 41));
+
+        all_eq!(simd_shuffle2(x8, y8, [11, 5]), i32x2(183, 85));
+        all_eq!(simd_shuffle3(x8, y8, [11, 5, 15]), i32x3(183, 85, 187));
+        all_eq!(simd_shuffle4(x8, y8, [11, 5, 15, 0]), i32x4(183, 85, 187, 80));
+        all_eq!(simd_shuffle8(x8, y8, [11, 5, 15, 0, 3, 8, 12, 1]),
+                i32x8(183, 85, 187, 80, 83, 180, 184, 81));
+    }
+
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-gather.rs b/src/test/ui/simd/simd-intrinsic-generic-gather.rs
new file mode 100644
index 00000000000..805caebe5b1
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-gather.rs
@@ -0,0 +1,141 @@
+// run-pass
+// ignore-emscripten
+
+// Test that the simd_{gather,scatter} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct x4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_gather<T, U, V>(x: T, y: U, z: V) -> T;
+    fn simd_scatter<T, U, V>(x: T, y: U, z: V) -> ();
+}
+
+fn main() {
+    let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
+
+    let default = x4(-3_f32, -3., -3., -3.);
+    let s_strided = x4(0_f32, 2., -3., 6.);
+    let mask = x4(-1_i32, -1, 0, -1);
+
+    // reading from *const
+    unsafe {
+        let pointer = &x[0] as *const f32;
+        let pointers =  x4(
+            pointer.offset(0) as *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // reading from *mut
+    unsafe {
+        let pointer = &mut x[0] as *mut f32;
+        let pointers = x4(
+            pointer.offset(0) as *mut f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // writing to *mut
+    unsafe {
+        let pointer = &mut x[0] as *mut f32;
+        let pointers = x4(
+            pointer.offset(0) as *mut f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let values = x4(42_f32, 43_f32, 44_f32, 45_f32);
+        simd_scatter(values, pointers, mask);
+
+        assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
+    }
+
+    // test modifying array of *const f32
+    let mut y = [
+        &x[0] as *const f32,
+        &x[1] as *const f32,
+        &x[2] as *const f32,
+        &x[3] as *const f32,
+        &x[4] as *const f32,
+        &x[5] as *const f32,
+        &x[6] as *const f32,
+        &x[7] as *const f32
+    ];
+
+    let default = x4(y[0], y[0], y[0], y[0]);
+    let s_strided = x4(y[0], y[2], y[0], y[6]);
+
+    // reading from *const
+    unsafe {
+        let pointer = &y[0] as *const *const f32;
+        let pointers = x4(
+            pointer.offset(0) as *const *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // reading from *mut
+    unsafe {
+        let pointer = &mut y[0] as *mut *const f32;
+        let pointers = x4(
+            pointer.offset(0) as *mut *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // writing to *mut
+    unsafe {
+        let pointer = &mut y[0] as *mut *const f32;
+        let pointers = x4(
+            pointer.offset(0) as *mut *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        );
+
+        let values = x4(y[7], y[6], y[5], y[1]);
+        simd_scatter(values, pointers, mask);
+
+        let s = [
+            &x[7] as *const f32,
+            &x[1] as *const f32,
+            &x[6] as *const f32,
+            &x[3] as *const f32,
+            &x[4] as *const f32,
+            &x[5] as *const f32,
+            &x[1] as *const f32,
+            &x[7] as *const f32
+        ];
+        assert_eq!(y, s);
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
new file mode 100644
index 00000000000..4195444a73f
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
@@ -0,0 +1,165 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// ignore-emscripten
+// min-system-llvm-version: 9.0
+
+// Test that the simd_reduce_{op} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x16(
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8
+);
+
+extern "platform-intrinsic" {
+    fn simd_reduce_add_unordered<T, U>(x: T) -> U;
+    fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
+    fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
+    fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
+    fn simd_reduce_min<T, U>(x: T) -> U;
+    fn simd_reduce_max<T, U>(x: T) -> U;
+    fn simd_reduce_min_nanless<T, U>(x: T) -> U;
+    fn simd_reduce_max_nanless<T, U>(x: T) -> U;
+    fn simd_reduce_and<T, U>(x: T) -> U;
+    fn simd_reduce_or<T, U>(x: T) -> U;
+    fn simd_reduce_xor<T, U>(x: T) -> U;
+    fn simd_reduce_all<T>(x: T) -> bool;
+    fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+    unsafe {
+        let x = i32x4(1, -2, 3, 4);
+        let r: i32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 6_i32);
+        let r: i32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, -24_i32);
+        let r: i32 = simd_reduce_add_ordered(x, -1);
+        assert_eq!(r, 5_i32);
+        let r: i32 = simd_reduce_mul_ordered(x, -1);
+        assert_eq!(r, 24_i32);
+
+        let r: i32 = simd_reduce_min(x);
+        assert_eq!(r, -2_i32);
+        let r: i32 = simd_reduce_max(x);
+        assert_eq!(r, 4_i32);
+
+        let x = i32x4(-1, -1, -1, -1);
+        let r: i32 = simd_reduce_and(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_or(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_xor(x);
+        assert_eq!(r, 0_i32);
+
+        let x = i32x4(-1, -1, 0, -1);
+        let r: i32 = simd_reduce_and(x);
+        assert_eq!(r, 0_i32);
+        let r: i32 = simd_reduce_or(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_xor(x);
+        assert_eq!(r, -1_i32);
+    }
+
+    unsafe {
+        let x = u32x4(1, 2, 3, 4);
+        let r: u32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 10_u32);
+        let r: u32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, 24_u32);
+        let r: u32 = simd_reduce_add_ordered(x, 1);
+        assert_eq!(r, 11_u32);
+        let r: u32 = simd_reduce_mul_ordered(x, 2);
+        assert_eq!(r, 48_u32);
+
+        let r: u32 = simd_reduce_min(x);
+        assert_eq!(r, 1_u32);
+        let r: u32 = simd_reduce_max(x);
+        assert_eq!(r, 4_u32);
+
+        let t = u32::max_value();
+        let x = u32x4(t, t, t, t);
+        let r: u32 = simd_reduce_and(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_or(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_xor(x);
+        assert_eq!(r, 0_u32);
+
+        let x = u32x4(t, t, 0, t);
+        let r: u32 = simd_reduce_and(x);
+        assert_eq!(r, 0_u32);
+        let r: u32 = simd_reduce_or(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_xor(x);
+        assert_eq!(r, t);
+    }
+
+    unsafe {
+        let x = f32x4(1., -2., 3., 4.);
+        let r: f32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 6_f32);
+        let r: f32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, -24_f32);
+        let r: f32 = simd_reduce_add_ordered(x, 0.);
+        assert_eq!(r, 6_f32);
+        let r: f32 = simd_reduce_mul_ordered(x, 1.);
+        assert_eq!(r, -24_f32);
+        let r: f32 = simd_reduce_add_ordered(x, 1.);
+        assert_eq!(r, 7_f32);
+        let r: f32 = simd_reduce_mul_ordered(x, 2.);
+        assert_eq!(r, -48_f32);
+
+        let r: f32 = simd_reduce_min(x);
+        assert_eq!(r, -2_f32);
+        let r: f32 = simd_reduce_max(x);
+        assert_eq!(r, 4_f32);
+        let r: f32 = simd_reduce_min_nanless(x);
+        assert_eq!(r, -2_f32);
+        let r: f32 = simd_reduce_max_nanless(x);
+        assert_eq!(r, 4_f32);
+    }
+
+    unsafe {
+        let x = b8x4(!0, !0, !0, !0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, true);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, true);
+
+        let x = b8x4(!0, !0, 0, !0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, false);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, true);
+
+        let x = b8x4(0, 0, 0, 0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, false);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, false);
+    }
+}
diff --git a/src/test/ui/simd/simd-intrinsic-generic-select.rs b/src/test/ui/simd/simd-intrinsic-generic-select.rs
new file mode 100644
index 00000000000..22bda4fc9d9
--- /dev/null
+++ b/src/test/ui/simd/simd-intrinsic-generic-select.rs
@@ -0,0 +1,173 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+// ignore-emscripten
+// ignore-mips       behavior of simd_select_bitmask is endian-specific
+// ignore-mips64     behavior of simd_select_bitmask is endian-specific
+// ignore-powerpc    behavior of simd_select_bitmask is endian-specific
+// ignore-powerpc64  behavior of simd_select_bitmask is endian-specific
+
+// Test that the simd_select intrinsics produces correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+extern "platform-intrinsic" {
+    fn simd_select<T, U>(x: T, a: U, b: U) -> U;
+    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
+}
+
+fn main() {
+    let m0 = b8x4(!0, !0, !0, !0);
+    let m1 = b8x4(0, 0, 0, 0);
+    let m2 = b8x4(!0, !0, 0, 0);
+    let m3 = b8x4(0, 0, !0, !0);
+    let m4 = b8x4(!0, 0, !0, 0);
+
+    unsafe {
+        let a = i32x4(1, -2, 3, 4);
+        let b = i32x4(5, 6, -7, 8);
+
+        let r: i32x4 = simd_select(m0, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: i32x4 = simd_select(m1, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: i32x4 = simd_select(m2, a, b);
+        let e = i32x4(1, -2, -7, 8);
+        assert_eq!(r, e);
+
+        let r: i32x4 = simd_select(m3, a, b);
+        let e = i32x4(5, 6, 3, 4);
+        assert_eq!(r, e);
+
+        let r: i32x4 = simd_select(m4, a, b);
+        let e = i32x4(1, 6, 3, 8);
+        assert_eq!(r, e);
+    }
+
+    unsafe {
+        let a = u32x4(1, 2, 3, 4);
+        let b = u32x4(5, 6, 7, 8);
+
+        let r: u32x4 = simd_select(m0, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select(m1, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select(m2, a, b);
+        let e = u32x4(1, 2, 7, 8);
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select(m3, a, b);
+        let e = u32x4(5, 6, 3, 4);
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select(m4, a, b);
+        let e = u32x4(1, 6, 3, 8);
+        assert_eq!(r, e);
+    }
+
+    unsafe {
+        let a = f32x4(1., 2., 3., 4.);
+        let b = f32x4(5., 6., 7., 8.);
+
+        let r: f32x4 = simd_select(m0, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: f32x4 = simd_select(m1, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: f32x4 = simd_select(m2, a, b);
+        let e = f32x4(1., 2., 7., 8.);
+        assert_eq!(r, e);
+
+        let r: f32x4 = simd_select(m3, a, b);
+        let e = f32x4(5., 6., 3., 4.);
+        assert_eq!(r, e);
+
+        let r: f32x4 = simd_select(m4, a, b);
+        let e = f32x4(1., 6., 3., 8.);
+        assert_eq!(r, e);
+    }
+
+    unsafe {
+        let t = !0 as i8;
+        let f = 0 as i8;
+        let a = b8x4(t, f, t, f);
+        let b = b8x4(f, f, f, t);
+
+        let r: b8x4 = simd_select(m0, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: b8x4 = simd_select(m1, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: b8x4 = simd_select(m2, a, b);
+        let e = b8x4(t, f, f, t);
+        assert_eq!(r, e);
+
+        let r: b8x4 = simd_select(m3, a, b);
+        let e = b8x4(f, f, t, f);
+        assert_eq!(r, e);
+
+        let r: b8x4 = simd_select(m4, a, b);
+        let e = b8x4(t, f, t, t);
+        assert_eq!(r, e);
+    }
+
+    unsafe {
+        let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7);
+        let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15);
+
+        let r: u32x8 = simd_select_bitmask(0u8, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0xffu8, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
+        let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15);
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
+        let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7);
+        assert_eq!(r, e);
+
+        let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
+        let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
+        assert_eq!(r, e);
+    }
+}
diff --git a/src/test/ui/simd/simd-size-align.rs b/src/test/ui/simd/simd-size-align.rs
new file mode 100644
index 00000000000..556013788c3
--- /dev/null
+++ b/src/test/ui/simd/simd-size-align.rs
@@ -0,0 +1,96 @@
+// run-pass
+#![allow(deprecated)]
+
+
+#![feature(repr_simd)]
+#![allow(non_camel_case_types)]
+
+use std::mem;
+
+/// `T` should satisfy `size_of T (mod min_align_of T) === 0` to be stored at `Vec<T>` properly
+/// Please consult the issue #20460
+fn check<T>() {
+    assert_eq!(mem::size_of::<T>() % mem::min_align_of::<T>(), 0)
+}
+
+fn main() {
+    check::<u8x2>();
+    check::<u8x3>();
+    check::<u8x4>();
+    check::<u8x5>();
+    check::<u8x6>();
+    check::<u8x7>();
+    check::<u8x8>();
+
+    check::<i16x2>();
+    check::<i16x3>();
+    check::<i16x4>();
+    check::<i16x5>();
+    check::<i16x6>();
+    check::<i16x7>();
+    check::<i16x8>();
+
+    check::<f32x2>();
+    check::<f32x3>();
+    check::<f32x4>();
+    check::<f32x5>();
+    check::<f32x6>();
+    check::<f32x7>();
+    check::<f32x8>();
+
+    check::<usizex2>();
+    check::<usizex3>();
+    check::<usizex4>();
+    check::<usizex5>();
+    check::<usizex6>();
+    check::<usizex7>();
+    check::<usizex8>();
+
+    check::<isizex2>();
+    check::<isizex3>();
+    check::<isizex4>();
+    check::<isizex5>();
+    check::<isizex6>();
+    check::<isizex7>();
+    check::<isizex8>();
+}
+
+#[repr(simd)] struct u8x2(u8, u8);
+#[repr(simd)] struct u8x3(u8, u8, u8);
+#[repr(simd)] struct u8x4(u8, u8, u8, u8);
+#[repr(simd)] struct u8x5(u8, u8, u8, u8, u8);
+#[repr(simd)] struct u8x6(u8, u8, u8, u8, u8, u8);
+#[repr(simd)] struct u8x7(u8, u8, u8, u8, u8, u8, u8);
+#[repr(simd)] struct u8x8(u8, u8, u8, u8, u8, u8, u8, u8);
+
+#[repr(simd)] struct i16x2(i16, i16);
+#[repr(simd)] struct i16x3(i16, i16, i16);
+#[repr(simd)] struct i16x4(i16, i16, i16, i16);
+#[repr(simd)] struct i16x5(i16, i16, i16, i16, i16);
+#[repr(simd)] struct i16x6(i16, i16, i16, i16, i16, i16);
+#[repr(simd)] struct i16x7(i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)] struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+#[repr(simd)] struct f32x2(f32, f32);
+#[repr(simd)] struct f32x3(f32, f32, f32);
+#[repr(simd)] struct f32x4(f32, f32, f32, f32);
+#[repr(simd)] struct f32x5(f32, f32, f32, f32, f32);
+#[repr(simd)] struct f32x6(f32, f32, f32, f32, f32, f32);
+#[repr(simd)] struct f32x7(f32, f32, f32, f32, f32, f32, f32);
+#[repr(simd)] struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
+
+#[repr(simd)] struct usizex2(usize, usize);
+#[repr(simd)] struct usizex3(usize, usize, usize);
+#[repr(simd)] struct usizex4(usize, usize, usize, usize);
+#[repr(simd)] struct usizex5(usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex6(usize, usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex7(usize, usize, usize, usize, usize, usize, usize);
+#[repr(simd)] struct usizex8(usize, usize, usize, usize, usize, usize, usize, usize);
+
+#[repr(simd)] struct isizex2(isize, isize);
+#[repr(simd)] struct isizex3(isize, isize, isize);
+#[repr(simd)] struct isizex4(isize, isize, isize, isize);
+#[repr(simd)] struct isizex5(isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex6(isize, isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex7(isize, isize, isize, isize, isize, isize, isize);
+#[repr(simd)] struct isizex8(isize, isize, isize, isize, isize, isize, isize, isize);
diff --git a/src/test/ui/simd/simd-target-feature-mixup.rs b/src/test/ui/simd/simd-target-feature-mixup.rs
new file mode 100644
index 00000000000..6d7688191b7
--- /dev/null
+++ b/src/test/ui/simd/simd-target-feature-mixup.rs
@@ -0,0 +1,185 @@
+// run-pass
+#![allow(unused_variables)]
+#![allow(stable_features)]
+#![allow(overflowing_literals)]
+
+// ignore-emscripten
+// ignore-sgx no processes
+
+#![feature(repr_simd, target_feature, cfg_target_feature)]
+#![feature(avx512_target_feature)]
+
+use std::process::{Command, ExitStatus};
+use std::env;
+
+fn main() {
+    if let Some(level) = env::args().nth(1) {
+        return test::main(&level)
+    }
+
+    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 {
+    // An SSE type
+    #[repr(simd)]
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct __m128i(u64, u64);
+
+    // An AVX type
+    #[repr(simd)]
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct __m256i(u64, u64, u64, u64);
+
+    // An AVX-512 type
+    #[repr(simd)]
+    #[derive(PartialEq, Debug, Clone, Copy)]
+    struct __m512i(u64, u64, u64, u64, u64, u64, u64, u64);
+
+    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 = __m128i(1, 2);
+                let m256 = __m256i(3, 4, 5, 6);
+                let m512 = __m512i(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: __m128i) -> __m128i {
+        assert_eq!(a, __m128i(1, 2));
+        a.clone()
+    }
+
+    #[target_feature(enable = "sse2")]
+    unsafe fn id_sse_256(a: __m256i) -> __m256i {
+        assert_eq!(a, __m256i(3, 4, 5, 6));
+        a.clone()
+    }
+
+    #[target_feature(enable = "sse2")]
+    unsafe fn id_sse_512(a: __m512i) -> __m512i {
+        assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_128(a: __m128i) -> __m128i {
+        assert_eq!(a, __m128i(1, 2));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_256(a: __m256i) -> __m256i {
+        assert_eq!(a, __m256i(3, 4, 5, 6));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx")]
+    unsafe fn id_avx_512(a: __m512i) -> __m512i {
+        assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_128(a: __m128i) -> __m128i {
+        assert_eq!(a, __m128i(1, 2));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_256(a: __m256i) -> __m256i {
+        assert_eq!(a, __m256i(3, 4, 5, 6));
+        a.clone()
+    }
+
+    #[target_feature(enable = "avx512bw")]
+    unsafe fn id_avx512_512(a: __m512i) -> __m512i {
+        assert_eq!(a, __m512i(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) {}
+}
diff --git a/src/test/ui/simd/simd-type.rs b/src/test/ui/simd/simd-type.rs
new file mode 100644
index 00000000000..e7b9bfe32f8
--- /dev/null
+++ b/src/test/ui/simd/simd-type.rs
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct RGBA {
+    r: f32,
+    g: f32,
+    b: f32,
+    a: f32
+}
+
+pub fn main() {}