Skip to content

Commit 04fd2d3

Browse files
authored
Merge pull request rust-lang#230 from rust-lang/fix/simd_bitmask
Fix/simd bitmask
2 parents 44e3ea3 + f73dea7 commit 04fd2d3

File tree

4 files changed

+23
-20
lines changed

4 files changed

+23
-20
lines changed

failing-ui-tests.txt

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ src/test/ui/simd/issue-17170.rs
3838
src/test/ui/simd/issue-39720.rs
3939
src/test/ui/simd/issue-85915-simd-ptrs.rs
4040
src/test/ui/simd/issue-89193.rs
41-
src/test/ui/simd/simd-bitmask.rs
4241
src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs
4342
src/test/ui/sse2.rs
4443
src/test/ui/statics/issue-91050-1.rs

failing-ui-tests12.txt

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ src/test/ui/simd/intrinsic/inlining-issue67557-ice.rs
2020
src/test/ui/simd/intrinsic/inlining-issue67557.rs
2121
src/test/ui/simd/monomorphize-shuffle-index.rs
2222
src/test/ui/simd/shuffle.rs
23+
src/test/ui/simd/simd-bitmask.rs

src/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1613,9 +1613,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
16131613
let masks = self.bitcast_if_needed(masks, then_val.get_type());
16141614
let then_vals = masks & then_val;
16151615

1616-
let ones = vec![self.context.new_rvalue_one(element_type); num_units];
1617-
let ones = self.context.new_rvalue_from_vector(None, cond_type, &ones);
1618-
let inverted_masks = masks + ones;
1616+
let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units];
1617+
let minus_ones = self.context.new_rvalue_from_vector(None, cond_type, &minus_ones);
1618+
let inverted_masks = masks ^ minus_ones;
16191619
// NOTE: sometimes, the type of else_val can be different than the type of then_val in
16201620
// libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
16211621
// operation to work.

src/intrinsic/simd.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -337,36 +337,39 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
337337
let vector = args[0].immediate();
338338
let vector_type = vector.get_type().dyncast_vector().expect("vector type");
339339
let elem_type = vector_type.get_element_type();
340-
let mut shifts = vec![];
341-
let mut masks = vec![];
342-
let mut mask = 1;
343-
for i in 0..in_len {
344-
shifts.push(bx.context.new_rvalue_from_int(elem_type, i as i32));
345-
masks.push(bx.context.new_rvalue_from_int(elem_type, mask));
346-
mask <<= 1;
347-
}
348-
masks.reverse();
349-
let shifts = bx.context.new_rvalue_from_vector(None, vector.get_type(), &shifts);
350-
let shifted = vector >> shifts;
351-
let masks = bx.context.new_rvalue_from_vector(None, vector.get_type(), &masks);
352-
let masked = shifted & masks;
353-
let reduced = bx.vector_reduce_op(masked, BinaryOp::BitwiseOr);
354340

355341
let expected_int_bits = in_len.max(8);
356342
let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
357343

344+
// FIXME(antoyo): that's not going to work for masks bigger than 128 bits.
345+
let result_type = bx.type_ix(expected_int_bits);
346+
let mut result = bx.context.new_rvalue_zero(result_type);
347+
348+
let elem_size = elem_type.get_size() * 8;
349+
let sign_shift = bx.context.new_rvalue_from_int(elem_type, elem_size as i32);
350+
let one = bx.context.new_rvalue_one(elem_type);
351+
352+
let mut shift = 0;
353+
for i in 0..in_len {
354+
let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
355+
let shifted = elem >> sign_shift;
356+
let masked = shifted & one;
357+
result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift));
358+
shift += 1;
359+
}
360+
358361
match ret_ty.kind() {
359362
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {
360363
// Zero-extend iN to the bitmask type:
361-
return Ok(bx.zext(reduced, bx.type_ix(expected_int_bits)));
364+
return Ok(result);
362365
}
363366
ty::Array(elem, len)
364367
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
365368
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
366369
== Some(expected_bytes) =>
367370
{
368371
// Zero-extend iN to the array length:
369-
let ze = bx.zext(reduced, bx.type_ix(expected_bytes * 8));
372+
let ze = bx.zext(result, bx.type_ix(expected_bytes * 8));
370373

371374
// Convert the integer to a byte array
372375
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);

0 commit comments

Comments
 (0)