about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-12-14 22:10:21 +0800
committerkennytm <kennytm@gmail.com>2018-12-14 22:17:52 +0800
commit3397b79868cdbfa87b55fef77176a8e8084f04d9 (patch)
treee8b8991b50efee7c164dd85662278936de4f6aac /src/librustc_codegen_llvm
parent4a0ee22bc2fdeb2de198edc5c3916f0066080de9 (diff)
parent5087aef79202e9f1411a0d0a0a74b0e63643a118 (diff)
downloadrust-3397b79868cdbfa87b55fef77176a8e8084f04d9.tar.gz
rust-3397b79868cdbfa87b55fef77176a8e8084f04d9.zip
Rollup merge of #56789 - alexcrichton:simd_select_bitmask, r=rkruppe
rustc: Add an unstable `simd_select_bitmask` intrinsic

This is going to be required for binding a number of AVX-512 intrinsics
in the `stdsimd` repository, and this intrinsic is the same as
`simd_select` except that it takes a bitmask as the first argument
instead of a SIMD vector. This bitmask is then transmuted into a `<NN x
i8>` argument, depending on how many bits it is.

cc rust-lang-nursery/stdsimd#310
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 2b82ebe0bc2..8b26ada1576 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1171,6 +1171,27 @@ fn generic_simd_intrinsic(
     );
     let arg_tys = sig.inputs();
 
+    if name == "simd_select_bitmask" {
+        let in_ty = arg_tys[0];
+        let m_len = match in_ty.sty {
+            // Note that this `.unwrap()` crashes for isize/usize, that's sort
+            // of intentional as there's not currently a use case for that.
+            ty::Int(i) => i.bit_width().unwrap(),
+            ty::Uint(i) => i.bit_width().unwrap(),
+            _ => return_error!("`{}` is not an integral type", in_ty),
+        };
+        require_simd!(arg_tys[1], "argument");
+        let v_len = arg_tys[1].simd_size(tcx);
+        require!(m_len == v_len,
+                 "mismatched lengths: mask length `{}` != other vector length `{}`",
+                 m_len, v_len
+        );
+        let i1 = bx.type_i1();
+        let i1xn = bx.type_vector(i1, m_len as u64);
+        let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
+        return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
+    }
+
     // every intrinsic takes a SIMD vector as its first argument
     require_simd!(arg_tys[0], "input");
     let in_ty = arg_tys[0];