Skip to content

Commit f200fbc

Browse files
committed
Implement simd_bitmask
1 parent 0bb9bdf commit f200fbc

File tree

2 files changed

+111
-40
lines changed

2 files changed

+111
-40
lines changed

patches/0001-portable-simd-Disable-unsupported-tests.patch

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
From 82f597cf81b169b0e72a576ac8751f598c059c48 Mon Sep 17 00:00:00 2001
1+
From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001
22
From: bjorn3 <[email protected]>
33
Date: Thu, 18 Nov 2021 19:28:40 +0100
44
Subject: [PATCH] Disable unsupported tests
55

66
---
77
crates/core_simd/src/elements/int.rs | 8 ++++++++
88
crates/core_simd/src/elements/uint.rs | 4 ++++
9-
crates/core_simd/src/masks/full_masks.rs | 9 +++++++++
9+
crates/core_simd/src/masks/full_masks.rs | 6 ++++++
1010
crates/core_simd/src/vector.rs | 2 ++
11-
crates/core_simd/tests/masks.rs | 2 ++
12-
5 files changed, 25 insertions(+)
11+
crates/core_simd/tests/masks.rs | 3 ---
12+
5 files changed, 20 insertions(+), 3 deletions(-)
1313

1414
diff --git a/crates/core_simd/src/elements/int.rs b/crates/core_simd/src/elements/int.rs
1515
index 9b8c37e..ea95f08 100644
@@ -116,52 +116,35 @@ index 21e7e76..0d6dee2 100644
116116
#[inline]
117117
fn reduce_sum(self) -> Self::Scalar {
118118
diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs
119-
index adf0fcb..5b10292 100644
119+
index adf0fcb..e7e657e 100644
120120
--- a/crates/core_simd/src/masks/full_masks.rs
121121
+++ b/crates/core_simd/src/masks/full_masks.rs
122-
@@ -150,6 +150,7 @@ where
122+
@@ -180,6 +180,7 @@ where
123123
super::Mask<T, LANES>: ToBitMaskArray,
124124
[(); <super::Mask<T, LANES> as ToBitMaskArray>::BYTES]: Sized,
125125
{
126126
+ /*
127127
assert_eq!(<super::Mask<T, LANES> as ToBitMaskArray>::BYTES, N);
128128

129129
// Safety: N is the correct bitmask size
130-
@@ -170,6 +171,8 @@ where
131-
132-
bitmask
133-
}
134-
+ */
135-
+ panic!();
136-
}
137-
138-
#[cfg(feature = "generic_const_exprs")]
139-
@@ -209,6 +212,7 @@ where
140-
where
141-
super::Mask<T, LANES>: ToBitMask<BitMask = U>,
142-
{
143-
+ /*
144-
// Safety: U is required to be the appropriate bitmask type
145-
let bitmask: U = unsafe { intrinsics::simd_bitmask(self.0) };
146-
147-
@@ -218,6 +222,8 @@ where
148-
} else {
149-
bitmask
130+
@@ -202,6 +203,8 @@ where
131+
Self::splat(false).to_int(),
132+
))
150133
}
151134
+ */
152135
+ panic!();
153136
}
154137

155138
#[inline]
156-
@@ -225,6 +231,7 @@ where
139+
@@ -225,6 +228,7 @@ where
157140
where
158141
super::Mask<T, LANES>: ToBitMask<BitMask = U>,
159142
{
160143
+ /*
161144
// LLVM assumes bit order should match endianness
162145
let bitmask = if cfg!(target_endian = "big") {
163146
bitmask.reverse_bits(LANES)
164-
@@ -240,6 +247,8 @@ where
147+
@@ -240,6 +244,8 @@ where
165148
Self::splat(false).to_int(),
166149
))
167150
}
@@ -191,24 +174,30 @@ index e8e8f68..7173c24 100644
191174

192175
impl<T, const LANES: usize> Copy for Simd<T, LANES>
193176
diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
194-
index 673d0db..0d68b01 100644
177+
index 673d0db..3ebfcd1 100644
195178
--- a/crates/core_simd/tests/masks.rs
196179
+++ b/crates/core_simd/tests/masks.rs
197-
@@ -59,6 +59,7 @@ macro_rules! test_mask_api {
198-
assert!(!v.all());
180+
@@ -78,7 +78,6 @@ macro_rules! test_mask_api {
181+
let mask = core_simd::Mask::<$type, 16>::from_array(values);
182+
let bitmask = mask.to_bitmask();
183+
assert_eq!(bitmask, 0b1000001101001001);
184+
- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
199185
}
200186

201-
+ /*
202187
#[test]
203-
fn roundtrip_int_conversion() {
204-
let values = [true, false, false, true, false, false, true, false];
205-
@@ -99,6 +100,7 @@ macro_rules! test_mask_api {
188+
@@ -91,13 +90,11 @@ macro_rules! test_mask_api {
189+
let mask = core_simd::Mask::<$type, 4>::from_array(values);
190+
let bitmask = mask.to_bitmask();
191+
assert_eq!(bitmask, 0b1000);
192+
- assert_eq!(core_simd::Mask::<$type, 4>::from_bitmask(bitmask), mask);
193+
194+
let values = [true, false];
195+
let mask = core_simd::Mask::<$type, 2>::from_array(values);
196+
let bitmask = mask.to_bitmask();
206197
assert_eq!(bitmask, 0b01);
207-
assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask);
198+
- assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask);
208199
}
209-
+ */
210200

211201
#[test]
212-
fn cast() {
213202
--
214203
2.25.1

src/intrinsics/simd.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use rustc_middle::ty::subst::SubstsRef;
44
use rustc_span::Symbol;
5+
use rustc_target::abi::Endian;
56

67
use super::*;
78
use crate::prelude::*;
@@ -162,6 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
162163
}
163164
}
164165
} else {
166+
// FIXME remove this case
165167
intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
166168
};
167169

@@ -650,10 +652,90 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
650652
}
651653
}
652654

653-
// simd_saturating_*
654-
// simd_bitmask
655+
sym::simd_bitmask => {
656+
intrinsic_args!(fx, args => (a); intrinsic);
657+
658+
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
659+
let lane_clif_ty = fx.clif_type(lane_ty).unwrap();
660+
661+
// The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
662+
// vector mask and returns the most significant bit (MSB) of each lane in the form
663+
// of either:
664+
// * an unsigned integer
665+
// * an array of `u8`
666+
// If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
667+
//
668+
// The bit order of the result depends on the byte endianness, LSB-first for little
669+
// endian and MSB-first for big endian.
670+
let expected_int_bits = lane_count.max(8);
671+
let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
672+
673+
match lane_ty.kind() {
674+
ty::Int(_) | ty::Uint(_) => {}
675+
_ => {
676+
fx.tcx.sess.span_fatal(
677+
span,
678+
&format!(
679+
"invalid monomorphization of `simd_bitmask` intrinsic: \
680+
vector argument `{}`'s element type `{}`, expected integer element \
681+
type",
682+
a.layout().ty,
683+
lane_ty
684+
),
685+
);
686+
}
687+
}
688+
689+
let res_type =
690+
Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
691+
let mut res = fx.bcx.ins().iconst(res_type, 0);
692+
693+
let lanes = match fx.tcx.sess.target.endian {
694+
Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
695+
Endian::Little => Box::new((0..lane_count).rev()) as Box<dyn Iterator<Item = u64>>,
696+
};
697+
for lane in lanes {
698+
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
699+
700+
// extract sign bit of an int
701+
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_clif_ty.bits() - 1));
702+
703+
// shift sign bit into result
704+
let a_lane_sign = clif_intcast(fx, a_lane_sign, res_type, false);
705+
res = fx.bcx.ins().ishl_imm(res, 1);
706+
res = fx.bcx.ins().bor(res, a_lane_sign);
707+
}
708+
709+
match ret.layout().ty.kind() {
710+
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {}
711+
ty::Array(elem, len)
712+
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
713+
&& len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all())
714+
== Some(expected_bytes) => {}
715+
_ => {
716+
fx.tcx.sess.span_fatal(
717+
span,
718+
&format!(
719+
"invalid monomorphization of `simd_bitmask` intrinsic: \
720+
cannot return `{}`, expected `u{}` or `[u8; {}]`",
721+
ret.layout().ty,
722+
expected_int_bits,
723+
expected_bytes
724+
),
725+
);
726+
}
727+
}
728+
729+
let res = CValue::by_val(res, ret.layout());
730+
ret.write_cvalue(fx, res);
731+
}
732+
733+
// simd_arith_offset
734+
// simd_saturating_add
735+
// simd_saturating_sub
655736
// simd_scatter
656737
// simd_gather
738+
// simd_select_bitmask
657739
_ => {
658740
fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
659741
}

0 commit comments

Comments
 (0)