Skip to content

Commit bc329f6

Browse files
authored
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/stdarch#310
2 parents daf2a03 + 5087aef commit bc329f6

File tree

6 files changed

+97
-5
lines changed

6 files changed

+97
-5
lines changed

src/librustc_codegen_llvm/intrinsic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,27 @@ fn generic_simd_intrinsic(
11711171
);
11721172
let arg_tys = sig.inputs();
11731173

1174+
if name == "simd_select_bitmask" {
1175+
let in_ty = arg_tys[0];
1176+
let m_len = match in_ty.sty {
1177+
// Note that this `.unwrap()` crashes for isize/usize, that's sort
1178+
// of intentional as there's not currently a use case for that.
1179+
ty::Int(i) => i.bit_width().unwrap(),
1180+
ty::Uint(i) => i.bit_width().unwrap(),
1181+
_ => return_error!("`{}` is not an integral type", in_ty),
1182+
};
1183+
require_simd!(arg_tys[1], "argument");
1184+
let v_len = arg_tys[1].simd_size(tcx);
1185+
require!(m_len == v_len,
1186+
"mismatched lengths: mask length `{}` != other vector length `{}`",
1187+
m_len, v_len
1188+
);
1189+
let i1 = bx.type_i1();
1190+
let i1xn = bx.type_vector(i1, m_len as u64);
1191+
let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
1192+
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
1193+
}
1194+
11741195
// every intrinsic takes a SIMD vector as its first argument
11751196
require_simd!(arg_tys[0], "input");
11761197
let in_ty = arg_tys[0];

src/librustc_typeck/check/intrinsic.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
435435
"simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
436436
"simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
437437
"simd_cast" => (2, vec![param(0)], param(1)),
438-
"simd_select" => (2, vec![param(0), param(1), param(1)], param(1)),
438+
"simd_select" |
439+
"simd_select_bitmask" => (2, vec![param(0), param(1), param(1)], param(1)),
439440
"simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
440441
"simd_reduce_add_ordered" | "simd_reduce_mul_ordered"
441442
=> (2, vec![param(0), param(1)], param(1)),

src/test/codegen/simd-intrinsic-generic-select.rs

+12
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@
1919
#[derive(Copy, Clone, PartialEq, Debug)]
2020
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
2121

22+
#[repr(simd)]
23+
#[derive(Copy, Clone, PartialEq, Debug)]
24+
pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
25+
2226
#[repr(simd)]
2327
#[derive(Copy, Clone, PartialEq, Debug)]
2428
pub struct b8x4(pub i8, pub i8, pub i8, pub i8);
2529

2630
extern "platform-intrinsic" {
2731
fn simd_select<T, U>(x: T, a: U, b: U) -> U;
32+
fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
2833
}
2934

3035
// CHECK-LABEL: @select
@@ -33,3 +38,10 @@ pub unsafe fn select(m: b8x4, a: f32x4, b: f32x4) -> f32x4 {
3338
// CHECK: select <4 x i1>
3439
simd_select(m, a, b)
3540
}
41+
42+
// CHECK-LABEL: @select_bitmask
43+
#[no_mangle]
44+
pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 {
45+
// CHECK: select <8 x i1>
46+
simd_select_bitmask(m, a, b)
47+
}

src/test/run-pass/simd/simd-intrinsic-generic-select.rs

+30
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ struct i32x4(pub i32, pub i32, pub i32, pub i32);
2626
#[derive(Copy, Clone, PartialEq, Debug)]
2727
struct u32x4(pub u32, pub u32, pub u32, pub u32);
2828

29+
#[repr(simd)]
30+
#[derive(Copy, Clone, PartialEq, Debug)]
31+
struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32);
32+
2933
#[repr(simd)]
3034
#[derive(Copy, Clone, PartialEq, Debug)]
3135
struct f32x4(pub f32, pub f32, pub f32, pub f32);
@@ -36,6 +40,7 @@ struct b8x4(pub i8, pub i8, pub i8, pub i8);
3640

3741
extern "platform-intrinsic" {
3842
fn simd_select<T, U>(x: T, a: U, b: U) -> U;
43+
fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
3944
}
4045

4146
fn main() {
@@ -146,4 +151,29 @@ fn main() {
146151
let e = b8x4(t, f, t, t);
147152
assert_eq!(r, e);
148153
}
154+
155+
unsafe {
156+
let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7);
157+
let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15);
158+
159+
let r: u32x8 = simd_select_bitmask(0u8, a, b);
160+
let e = b;
161+
assert_eq!(r, e);
162+
163+
let r: u32x8 = simd_select_bitmask(0xffu8, a, b);
164+
let e = a;
165+
assert_eq!(r, e);
166+
167+
let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
168+
let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15);
169+
assert_eq!(r, e);
170+
171+
let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
172+
let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7);
173+
assert_eq!(r, e);
174+
175+
let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
176+
let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
177+
assert_eq!(r, e);
178+
}
149179
}

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

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct b8x8(pub i8, pub i8, pub i8, pub i8,
3333

3434
extern "platform-intrinsic" {
3535
fn simd_select<T, U>(x: T, a: U, b: U) -> U;
36+
fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
3637
}
3738

3839
fn main() {
@@ -52,5 +53,14 @@ fn main() {
5253

5354
simd_select(z, z, z);
5455
//~^ ERROR mask element type is `f32`, expected `i_`
56+
57+
simd_select_bitmask(0u8, x, x);
58+
//~^ ERROR mask length `8` != other vector length `4`
59+
60+
simd_select_bitmask(0.0f32, x, x);
61+
//~^ ERROR `f32` is not an integral type
62+
63+
simd_select_bitmask("x", x, x);
64+
//~^ ERROR `&str` is not an integral type
5565
}
5666
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,39 @@
11
error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
2-
--> $DIR/simd-intrinsic-generic-select.rs:47:9
2+
--> $DIR/simd-intrinsic-generic-select.rs:48:9
33
|
44
LL | simd_select(m8, x, x);
55
| ^^^^^^^^^^^^^^^^^^^^^
66

77
error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
8-
--> $DIR/simd-intrinsic-generic-select.rs:50:9
8+
--> $DIR/simd-intrinsic-generic-select.rs:51:9
99
|
1010
LL | simd_select(x, x, x);
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
14-
--> $DIR/simd-intrinsic-generic-select.rs:53:9
14+
--> $DIR/simd-intrinsic-generic-select.rs:54:9
1515
|
1616
LL | simd_select(z, z, z);
1717
| ^^^^^^^^^^^^^^^^^^^^
1818

19-
error: aborting due to 3 previous errors
19+
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
20+
--> $DIR/simd-intrinsic-generic-select.rs:57:9
21+
|
22+
LL | simd_select_bitmask(0u8, x, x);
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
26+
--> $DIR/simd-intrinsic-generic-select.rs:60:9
27+
|
28+
LL | simd_select_bitmask(0.0f32, x, x);
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
32+
--> $DIR/simd-intrinsic-generic-select.rs:63:9
33+
|
34+
LL | simd_select_bitmask("x", x, x);
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
37+
error: aborting due to 6 previous errors
2038

2139
For more information about this error, try `rustc --explain E0511`.

0 commit comments

Comments
 (0)