diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 7f5b09eac4f9e..e76e86f56510b 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 a719b31415055..7d68af49e2868 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 f68c969d13ee3..a1ef0bb8ee03b 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 dc9ec5d2760fe..b850cf9750a1f 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); + } }