about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-12-13 12:50:42 -0800
committerAlex Crichton <alex@alexcrichton.com>2018-12-13 14:05:12 -0800
commit5087aef79202e9f1411a0d0a0a74b0e63643a118 (patch)
treec698acf4b9af6e33b6165340583a4d1588ca7007 /src/librustc_codegen_llvm
parentf4a421ee3cf1259f0750ac7fabd19da1d8551e4c (diff)
downloadrust-5087aef79202e9f1411a0d0a0a74b0e63643a118.tar.gz
rust-5087aef79202e9f1411a0d0a0a74b0e63643a118.zip
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];