about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs10
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs4
-rw-r--r--src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr6
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-select.rs25
4 files changed, 37 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 7f5b09eac4f..e76e86f5651 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -793,14 +793,18 @@ fn generic_simd_intrinsic(
         require_simd!(arg_tys[1], "argument");
         let v_len = arg_tys[1].simd_size(tcx);
         require!(
-            m_len == v_len,
+            // Allow masks for vectors with fewer than 8 elements to be
+            // represented with a u8 or i8.
+            m_len == v_len || (m_len == 8 && v_len < 8),
             "mismatched lengths: mask length `{}` != other vector length `{}`",
             m_len,
             v_len
         );
         let i1 = bx.type_i1();
-        let i1xn = bx.type_vector(i1, m_len);
-        let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
+        let im = bx.type_ix(v_len);
+        let i1xn = bx.type_vector(i1, v_len);
+        let m_im = bx.trunc(args[0].immediate(), im);
+        let m_i1s = bx.bitcast(m_im, i1xn);
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
 
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
index a719b314150..7d68af49e28 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs
@@ -49,8 +49,8 @@ fn main() {
         simd_select(m4, 0u32, 1u32);
         //~^ ERROR found non-SIMD `u32`
 
-        simd_select_bitmask(0u8, x, x);
-        //~^ ERROR mask length `8` != other vector length `4`
+        simd_select_bitmask(0u16, x, x);
+        //~^ ERROR mask length `16` != other vector length `4`
         //
         simd_select_bitmask(0u8, 1u32, 2u32);
         //~^ ERROR found non-SIMD `u32`
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
index f68c969d13e..a1ef0bb8ee0 100644
--- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr
@@ -22,11 +22,11 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD
 LL |         simd_select(m4, 0u32, 1u32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `16` != other vector length `4`
   --> $DIR/simd-intrinsic-generic-select.rs:52:9
    |
-LL |         simd_select_bitmask(0u8, x, x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         simd_select_bitmask(0u16, x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
   --> $DIR/simd-intrinsic-generic-select.rs:55:9
diff --git a/src/test/ui/simd/simd-intrinsic-generic-select.rs b/src/test/ui/simd/simd-intrinsic-generic-select.rs
index dc9ec5d2760..b850cf9750a 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-select.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-select.rs
@@ -167,4 +167,29 @@ fn main() {
         let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
         assert_eq!(r, e);
     }
+
+    unsafe {
+        let a = u32x4(0, 1, 2, 3);
+        let b = u32x4(4, 5, 6, 7);
+
+        let r: u32x4 = simd_select_bitmask(0u8, a, b);
+        let e = b;
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select_bitmask(0xfu8, a, b);
+        let e = a;
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select_bitmask(0b0101u8, a, b);
+        let e = u32x4(0, 5, 2, 7);
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select_bitmask(0b1010u8, a, b);
+        let e = u32x4(4, 1, 6, 3);
+        assert_eq!(r, e);
+
+        let r: u32x4 = simd_select_bitmask(0b1100u8, a, b);
+        let e = u32x4(4, 5, 2, 3);
+        assert_eq!(r, e);
+    }
 }