about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-24 13:11:06 +0000
committerbors <bors@rust-lang.org>2019-01-24 13:11:06 +0000
commit095b44c83b540bb4dbf74be1cae604f4bae87989 (patch)
tree660a01091b2a50604735d6d3ddaa862dadb238c9 /src/test
parentf23b63cbbf8d92deac6b3c39746d3b85d3e838af (diff)
parent785f529d6e91b787d94b44726a5d6018e8fe181b (diff)
Auto merge of #57269 - gnzlbg:simd_bitmask, r=rkruppe
Add intrinsic to create an integer bitmask from a vector mask

This PR adds a new simd intrinsic: `simd_bitmask(vector) -> unsigned integer` that creates an integer bitmask from a vector mask by extracting one bit of each vector lane.

This is required to implement: https://github.com/rust-lang-nursery/packed_simd/issues/166 .

EDIT: the reason we need an intrinsics for this is that we have to truncate the vector lanes to an `<i1 x N>` vector, and then bitcast that to an `iN` integer (while making sure that we only materialize `i8`, ... , `i64` - that is, no `i1`, `i2`, `i4`, types), and we can't do any of that in a Rust library.

r? @rkruppe
Diffstat (limited to 'src/test')
-rw-r--r--src/test/codegen/simd-intrinsic-generic-bitmask.rs57
-rw-r--r--src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs61
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs90
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr33
4 files changed, 241 insertions, 0 deletions
diff --git a/src/test/codegen/simd-intrinsic-generic-bitmask.rs b/src/test/codegen/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 00000000000..cd8130f9231
--- /dev/null
+++ b/src/test/codegen/simd-intrinsic-generic-bitmask.rs
@@ -0,0 +1,57 @@
+// compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(u32, u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i32x2(i32, i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct i8x16(
+    i8, i8, i8, i8, i8, i8, i8, i8,
+    i8, i8, i8, i8, i8, i8, i8, i8,
+);
+
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+// CHECK-LABEL: @bitmask_int
+#[no_mangle]
+pub unsafe fn bitmask_int(x: i32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_uint
+#[no_mangle]
+pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, <i32 31, i32 31>
+    // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
+    // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
+    // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
+    simd_bitmask(x)
+}
+
+// CHECK-LABEL: @bitmask_int16
+#[no_mangle]
+pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
+    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9]+}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
+    // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
+    // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
+    // CHECK-NOT: zext
+    simd_bitmask(x)
+}
diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs b/src/test/run-pass/simd/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 00000000000..b28f742a92e
--- /dev/null
+++ b/src/test/run-pass/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-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
new file mode 100644
index 00000000000..931ee9db1fe
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -0,0 +1,90 @@
+// Test that the simd_bitmask intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x2(pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x8(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x16(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x32(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u8x64(
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+    pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8,
+);
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(x: T) -> U;
+}
+
+fn main() {
+    let m2 = u32x2(0, 0);
+    let m4 = u32x4(0, 0, 0, 0);
+    let m8 = u8x8(0, 0, 0, 0, 0, 0, 0, 0);
+    let m16 = u8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m32 = u8x32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    let m64 = u8x64(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+    unsafe {
+        let _: u8 = simd_bitmask(m2);
+        let _: u8 = simd_bitmask(m4);
+        let _: u8 = simd_bitmask(m8);
+        let _: u16 = simd_bitmask(m16);
+        let _: u32 = simd_bitmask(m32);
+        let _: u64 = simd_bitmask(m64);
+
+        let _: u16 = simd_bitmask(m2);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u16 = simd_bitmask(m8);
+        //~^ ERROR bitmask `u16`, expected `u8`
+
+        let _: u32 = simd_bitmask(m16);
+        //~^ ERROR bitmask `u32`, expected `u16`
+
+        let _: u64 = simd_bitmask(m32);
+        //~^ ERROR bitmask `u64`, expected `u32`
+
+        let _: u128 = simd_bitmask(m64);
+        //~^ ERROR bitmask `u128`, expected `u64`
+
+   }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
new file mode 100644
index 00000000000..d016838d098
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr
@@ -0,0 +1,33 @@
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:74:22
+   |
+LL |         let _: u16 = simd_bitmask(m2);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:77:22
+   |
+LL |         let _: u16 = simd_bitmask(m8);
+   |                      ^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:80:22
+   |
+LL |         let _: u32 = simd_bitmask(m16);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:83:22
+   |
+LL |         let _: u64 = simd_bitmask(m32);
+   |                      ^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
+  --> $DIR/simd-intrinsic-generic-bitmask.rs:86:23
+   |
+LL |         let _: u128 = simd_bitmask(m64);
+   |                       ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0511`.