Allow simd_select_bitmask to take byte arrays
This commit is contained in:
parent
7964942515
commit
3981ca076c
4 changed files with 70 additions and 37 deletions
|
@ -857,28 +857,39 @@ fn generic_simd_intrinsic(
|
|||
let arg_tys = sig.inputs();
|
||||
|
||||
if name == sym::simd_select_bitmask {
|
||||
let in_ty = arg_tys[0];
|
||||
let m_len = match in_ty.kind() {
|
||||
// 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_and_type(bx.tcx());
|
||||
require!(
|
||||
// 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 (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
|
||||
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
|
||||
let expected_bytes = len / 8 + ((len % 8 > 1) as u64);
|
||||
|
||||
let mask_ty = arg_tys[0];
|
||||
let mask = match mask_ty.kind() {
|
||||
ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
||||
ty::Array(elem, len)
|
||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
|
||||
== Some(expected_bytes) =>
|
||||
{
|
||||
let place = PlaceRef::alloca(bx, args[0].layout);
|
||||
args[0].val.store(bx, place);
|
||||
let int_ty = bx.type_ix(expected_bytes * 8);
|
||||
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
|
||||
bx.load(int_ty, ptr, Align::ONE)
|
||||
}
|
||||
_ => return_error!(
|
||||
"invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
|
||||
mask_ty,
|
||||
expected_int_bits,
|
||||
expected_bytes
|
||||
),
|
||||
};
|
||||
|
||||
let i1 = bx.type_i1();
|
||||
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 im = bx.type_ix(len);
|
||||
let i1xn = bx.type_vector(i1, len);
|
||||
let m_im = bx.trunc(mask, im);
|
||||
let m_i1s = bx.bitcast(m_im, i1xn);
|
||||
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue