Skip to content

Commit 7964942

Browse files
committed
Allow simd_bitmask to return byte arrays
1 parent 0d1754e commit 7964942

File tree

4 files changed

+73
-22
lines changed

4 files changed

+73
-22
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+35-12
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
1919
use rustc_middle::ty::{self, Ty};
2020
use rustc_middle::{bug, span_bug};
2121
use rustc_span::{sym, symbol::kw, Span, Symbol};
22-
use rustc_target::abi::{self, HasDataLayout, Primitive};
22+
use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
2323
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
2424

2525
use std::cmp::Ordering;
@@ -1056,16 +1056,13 @@ fn generic_simd_intrinsic(
10561056

10571057
if name == sym::simd_bitmask {
10581058
// The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
1059-
// vector mask and returns an unsigned integer containing the most
1060-
// significant bit (MSB) of each lane.
1061-
1062-
// If the vector has less than 8 lanes, a u8 is returned with zeroed
1063-
// trailing bits.
1059+
// vector mask and returns the most significant bit (MSB) of each lane in the form
1060+
// of either:
1061+
// * an unsigned integer
1062+
// * an array of `u8`
1063+
// If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
10641064
let expected_int_bits = in_len.max(8);
1065-
match ret_ty.kind() {
1066-
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (),
1067-
_ => return_error!("bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits),
1068-
}
1065+
let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 1) as u64);
10691066

10701067
// Integer vector <i{in_bitwidth} x in_len>:
10711068
let (i_xn, in_elem_bitwidth) = match in_elem.kind() {
@@ -1095,8 +1092,34 @@ fn generic_simd_intrinsic(
10951092
let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
10961093
// Bitcast <i1 x N> to iN:
10971094
let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
1098-
// Zero-extend iN to the bitmask type:
1099-
return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
1095+
1096+
match ret_ty.kind() {
1097+
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {
1098+
// Zero-extend iN to the bitmask type:
1099+
return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
1100+
}
1101+
ty::Array(elem, len)
1102+
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
1103+
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
1104+
== Some(expected_bytes) =>
1105+
{
1106+
// Zero-extend iN to the array lengh:
1107+
let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
1108+
1109+
// Convert the integer to a byte array
1110+
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
1111+
bx.store(ze, ptr, Align::ONE);
1112+
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
1113+
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
1114+
return Ok(bx.load(array_ty, ptr, Align::ONE));
1115+
}
1116+
_ => return_error!(
1117+
"cannot return `{}`, expected `u{}` or `[u8; {}]`",
1118+
ret_ty,
1119+
expected_int_bits,
1120+
expected_bytes
1121+
),
1122+
}
11001123
}
11011124

11021125
fn simd_simple_float_intrinsic(

src/test/ui/simd/intrinsic/generic-bitmask.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,19 @@ fn main() {
5151
let _: u64 = simd_bitmask(m64);
5252

5353
let _: u16 = simd_bitmask(m2);
54-
//~^ ERROR bitmask `u16`, expected `u8`
54+
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
5555

5656
let _: u16 = simd_bitmask(m8);
57-
//~^ ERROR bitmask `u16`, expected `u8`
57+
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
5858

5959
let _: u32 = simd_bitmask(m16);
60-
//~^ ERROR bitmask `u32`, expected `u16`
60+
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
6161

6262
let _: u64 = simd_bitmask(m32);
63-
//~^ ERROR bitmask `u64`, expected `u32`
63+
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
6464

6565
let _: u128 = simd_bitmask(m64);
66-
//~^ ERROR bitmask `u128`, expected `u64`
66+
//~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
6767

6868
}
6969
}

src/test/ui/simd/intrinsic/generic-bitmask.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
1+
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
22
--> $DIR/generic-bitmask.rs:53:22
33
|
44
LL | let _: u16 = simd_bitmask(m2);
55
| ^^^^^^^^^^^^^^^^
66

7-
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
7+
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
88
--> $DIR/generic-bitmask.rs:56:22
99
|
1010
LL | let _: u16 = simd_bitmask(m8);
1111
| ^^^^^^^^^^^^^^^^
1212

13-
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
13+
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]`
1414
--> $DIR/generic-bitmask.rs:59:22
1515
|
1616
LL | let _: u32 = simd_bitmask(m16);
1717
| ^^^^^^^^^^^^^^^^^
1818

19-
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
19+
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]`
2020
--> $DIR/generic-bitmask.rs:62:22
2121
|
2222
LL | let _: u64 = simd_bitmask(m32);
2323
| ^^^^^^^^^^^^^^^^^
2424

25-
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
25+
error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]`
2626
--> $DIR/generic-bitmask.rs:65:23
2727
|
2828
LL | let _: u128 = simd_bitmask(m64);

src/test/ui/simd/simd-bitmask.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//run-pass
2+
#![feature(repr_simd, platform_intrinsics)]
3+
4+
extern "platform-intrinsic" {
5+
fn simd_bitmask<T, U>(v: T) -> U;
6+
}
7+
8+
#[derive(Copy, Clone)]
9+
#[repr(simd)]
10+
struct Simd<T, const N: usize>([T; N]);
11+
12+
fn main() {
13+
unsafe {
14+
let v = Simd::<i8, 4>([-1, 0, -1, 0]);
15+
let i: u8 = simd_bitmask(v);
16+
let a: [u8; 1] = simd_bitmask(v);
17+
18+
assert_eq!(i, 0b0101);
19+
assert_eq!(a, [0b0101]);
20+
21+
let v = Simd::<i8, 16>([0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0]);
22+
let i: u16 = simd_bitmask(v);
23+
let a: [u8; 2] = simd_bitmask(v);
24+
25+
assert_eq!(i, 0b0101000000001100);
26+
assert_eq!(a, [0b1100, 0b01010000]);
27+
}
28+
}

0 commit comments

Comments
 (0)