about summary refs log tree commit diff
diff options
context:
space:
mode:
authorantoyo <antoyo@users.noreply.github.com>2022-10-09 12:37:42 -0400
committerGitHub <noreply@github.com>2022-10-09 12:37:42 -0400
commit04fd2d3c9c58124b3038ff1e575d054660d836ab (patch)
tree17c369e64fb867671fcc965c1066ccad773a0f0b
parent44e3ea3e42918ff6a5d2083ddc0c4ece16309862 (diff)
parentf73dea7e55dcd14f36963f37a24dc9764c584252 (diff)
downloadrust-04fd2d3c9c58124b3038ff1e575d054660d836ab.tar.gz
rust-04fd2d3c9c58124b3038ff1e575d054660d836ab.zip
Merge pull request #230 from rust-lang/fix/simd_bitmask
Fix/simd bitmask
-rw-r--r--failing-ui-tests.txt1
-rw-r--r--failing-ui-tests12.txt1
-rw-r--r--src/builder.rs6
-rw-r--r--src/intrinsic/simd.rs35
4 files changed, 23 insertions, 20 deletions
diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt
index 6acd3808445..8a780e88147 100644
--- a/failing-ui-tests.txt
+++ b/failing-ui-tests.txt
@@ -38,7 +38,6 @@ src/test/ui/simd/issue-17170.rs
 src/test/ui/simd/issue-39720.rs
 src/test/ui/simd/issue-85915-simd-ptrs.rs
 src/test/ui/simd/issue-89193.rs
-src/test/ui/simd/simd-bitmask.rs
 src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs
 src/test/ui/sse2.rs
 src/test/ui/statics/issue-91050-1.rs
diff --git a/failing-ui-tests12.txt b/failing-ui-tests12.txt
index 027c929d2f3..00cd42d8e9d 100644
--- a/failing-ui-tests12.txt
+++ b/failing-ui-tests12.txt
@@ -20,3 +20,4 @@ src/test/ui/simd/intrinsic/inlining-issue67557-ice.rs
 src/test/ui/simd/intrinsic/inlining-issue67557.rs
 src/test/ui/simd/monomorphize-shuffle-index.rs
 src/test/ui/simd/shuffle.rs
+src/test/ui/simd/simd-bitmask.rs
diff --git a/src/builder.rs b/src/builder.rs
index f3933a2d706..ee9983830ff 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1613,9 +1613,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let masks = self.bitcast_if_needed(masks, then_val.get_type());
         let then_vals = masks & then_val;
 
-        let ones = vec![self.context.new_rvalue_one(element_type); num_units];
-        let ones = self.context.new_rvalue_from_vector(None, cond_type, &ones);
-        let inverted_masks = masks + ones;
+        let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units];
+        let minus_ones = self.context.new_rvalue_from_vector(None, cond_type, &minus_ones);
+        let inverted_masks = masks ^ minus_ones;
         // NOTE: sometimes, the type of else_val can be different than the type of then_val in
         // libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
         // operation to work.
diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs
index 00c541a8af7..7d789009826 100644
--- a/src/intrinsic/simd.rs
+++ b/src/intrinsic/simd.rs
@@ -337,28 +337,31 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         let vector = args[0].immediate();
         let vector_type = vector.get_type().dyncast_vector().expect("vector type");
         let elem_type = vector_type.get_element_type();
-        let mut shifts = vec![];
-        let mut masks = vec![];
-        let mut mask = 1;
-        for i in 0..in_len {
-            shifts.push(bx.context.new_rvalue_from_int(elem_type, i as i32));
-            masks.push(bx.context.new_rvalue_from_int(elem_type, mask));
-            mask <<= 1;
-        }
-        masks.reverse();
-        let shifts = bx.context.new_rvalue_from_vector(None, vector.get_type(), &shifts);
-        let shifted = vector >> shifts;
-        let masks = bx.context.new_rvalue_from_vector(None, vector.get_type(), &masks);
-        let masked = shifted & masks;
-        let reduced = bx.vector_reduce_op(masked, BinaryOp::BitwiseOr);
 
         let expected_int_bits = in_len.max(8);
         let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
 
+        // FIXME(antoyo): that's not going to work for masks bigger than 128 bits.
+        let result_type = bx.type_ix(expected_int_bits);
+        let mut result = bx.context.new_rvalue_zero(result_type);
+
+        let elem_size = elem_type.get_size() * 8;
+        let sign_shift = bx.context.new_rvalue_from_int(elem_type, elem_size as i32);
+        let one = bx.context.new_rvalue_one(elem_type);
+
+        let mut shift = 0;
+        for i in 0..in_len {
+            let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32));
+            let shifted = elem >> sign_shift;
+            let masked = shifted & one;
+            result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift));
+            shift += 1;
+        }
+
         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(reduced, bx.type_ix(expected_int_bits)));
+                return Ok(result);
             }
             ty::Array(elem, len)
                 if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
@@ -366,7 +369,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
                         == Some(expected_bytes) =>
             {
                 // Zero-extend iN to the array length:
-                let ze = bx.zext(reduced, bx.type_ix(expected_bytes * 8));
+                let ze = bx.zext(result, 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);