Allow simd_bitmask to return byte arrays
This commit is contained in:
parent
0d1754e8bf
commit
7964942515
@ -19,7 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
|
|||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
||||||
use rustc_target::abi::{self, HasDataLayout, Primitive};
|
use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
|
||||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -1056,16 +1056,13 @@ fn generic_simd_intrinsic(
|
|||||||
|
|
||||||
if name == sym::simd_bitmask {
|
if name == sym::simd_bitmask {
|
||||||
// The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
|
// The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
|
||||||
// vector mask and returns an unsigned integer containing the most
|
// vector mask and returns the most significant bit (MSB) of each lane in the form
|
||||||
// significant bit (MSB) of each lane.
|
// of either:
|
||||||
|
// * an unsigned integer
|
||||||
// If the vector has less than 8 lanes, a u8 is returned with zeroed
|
// * an array of `u8`
|
||||||
// trailing bits.
|
// If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
|
||||||
let expected_int_bits = in_len.max(8);
|
let expected_int_bits = in_len.max(8);
|
||||||
match ret_ty.kind() {
|
let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 1) as u64);
|
||||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (),
|
|
||||||
_ => return_error!("bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer vector <i{in_bitwidth} x in_len>:
|
// Integer vector <i{in_bitwidth} x in_len>:
|
||||||
let (i_xn, in_elem_bitwidth) = match in_elem.kind() {
|
let (i_xn, in_elem_bitwidth) = match in_elem.kind() {
|
||||||
@ -1095,8 +1092,34 @@ fn generic_simd_intrinsic(
|
|||||||
let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
|
let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
|
||||||
// Bitcast <i1 x N> to iN:
|
// Bitcast <i1 x N> to iN:
|
||||||
let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
|
let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
|
||||||
// Zero-extend iN to the bitmask type:
|
|
||||||
return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
|
match ret_ty.kind() {
|
||||||
|
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {
|
||||||
|
// Zero-extend iN to the bitmask type:
|
||||||
|
return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
|
||||||
|
}
|
||||||
|
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) =>
|
||||||
|
{
|
||||||
|
// Zero-extend iN to the array lengh:
|
||||||
|
let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
|
||||||
|
|
||||||
|
// Convert the integer to a byte array
|
||||||
|
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
|
||||||
|
bx.store(ze, ptr, Align::ONE);
|
||||||
|
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
|
||||||
|
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
|
||||||
|
return Ok(bx.load(array_ty, ptr, Align::ONE));
|
||||||
|
}
|
||||||
|
_ => return_error!(
|
||||||
|
"cannot return `{}`, expected `u{}` or `[u8; {}]`",
|
||||||
|
ret_ty,
|
||||||
|
expected_int_bits,
|
||||||
|
expected_bytes
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simd_simple_float_intrinsic(
|
fn simd_simple_float_intrinsic(
|
||||||
|
@ -51,19 +51,19 @@ fn main() {
|
|||||||
let _: u64 = simd_bitmask(m64);
|
let _: u64 = simd_bitmask(m64);
|
||||||
|
|
||||||
let _: u16 = simd_bitmask(m2);
|
let _: u16 = simd_bitmask(m2);
|
||||||
//~^ ERROR bitmask `u16`, expected `u8`
|
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
|
||||||
|
|
||||||
let _: u16 = simd_bitmask(m8);
|
let _: u16 = simd_bitmask(m8);
|
||||||
//~^ ERROR bitmask `u16`, expected `u8`
|
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
|
||||||
|
|
||||||
let _: u32 = simd_bitmask(m16);
|
let _: u32 = simd_bitmask(m16);
|
||||||
//~^ ERROR bitmask `u32`, expected `u16`
|
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
|
||||||
|
|
||||||
let _: u64 = simd_bitmask(m32);
|
let _: u64 = simd_bitmask(m32);
|
||||||
//~^ ERROR bitmask `u64`, expected `u32`
|
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
|
||||||
|
|
||||||
let _: u128 = simd_bitmask(m64);
|
let _: u128 = simd_bitmask(m64);
|
||||||
//~^ ERROR bitmask `u128`, expected `u64`
|
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
|
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
|
||||||
--> $DIR/generic-bitmask.rs:53:22
|
--> $DIR/generic-bitmask.rs:53:22
|
||||||
|
|
|
|
||||||
LL | let _: u16 = simd_bitmask(m2);
|
LL | let _: u16 = simd_bitmask(m2);
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
|
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
|
||||||
--> $DIR/generic-bitmask.rs:56:22
|
--> $DIR/generic-bitmask.rs:56:22
|
||||||
|
|
|
|
||||||
LL | let _: u16 = simd_bitmask(m8);
|
LL | let _: u16 = simd_bitmask(m8);
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
|
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]`
|
||||||
--> $DIR/generic-bitmask.rs:59:22
|
--> $DIR/generic-bitmask.rs:59:22
|
||||||
|
|
|
|
||||||
LL | let _: u32 = simd_bitmask(m16);
|
LL | let _: u32 = simd_bitmask(m16);
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
|
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]`
|
||||||
--> $DIR/generic-bitmask.rs:62:22
|
--> $DIR/generic-bitmask.rs:62:22
|
||||||
|
|
|
|
||||||
LL | let _: u64 = simd_bitmask(m32);
|
LL | let _: u64 = simd_bitmask(m32);
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
|
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]`
|
||||||
--> $DIR/generic-bitmask.rs:65:23
|
--> $DIR/generic-bitmask.rs:65:23
|
||||||
|
|
|
|
||||||
LL | let _: u128 = simd_bitmask(m64);
|
LL | let _: u128 = simd_bitmask(m64);
|
||||||
|
28
src/test/ui/simd/simd-bitmask.rs
Normal file
28
src/test/ui/simd/simd-bitmask.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//run-pass
|
||||||
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
|
||||||
|
extern "platform-intrinsic" {
|
||||||
|
fn simd_bitmask<T, U>(v: T) -> U;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(simd)]
|
||||||
|
struct Simd<T, const N: usize>([T; N]);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
let v = Simd::<i8, 4>([-1, 0, -1, 0]);
|
||||||
|
let i: u8 = simd_bitmask(v);
|
||||||
|
let a: [u8; 1] = simd_bitmask(v);
|
||||||
|
|
||||||
|
assert_eq!(i, 0b0101);
|
||||||
|
assert_eq!(a, [0b0101]);
|
||||||
|
|
||||||
|
let v = Simd::<i8, 16>([0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0]);
|
||||||
|
let i: u16 = simd_bitmask(v);
|
||||||
|
let a: [u8; 2] = simd_bitmask(v);
|
||||||
|
|
||||||
|
assert_eq!(i, 0b0101000000001100);
|
||||||
|
assert_eq!(a, [0b1100, 0b01010000]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user