about summary refs log tree commit diff
diff options
context:
space:
mode:
authorantoyo <antoyo@users.noreply.github.com>2022-08-30 21:08:04 -0400
committerGitHub <noreply@github.com>2022-08-30 21:08:04 -0400
commitf623e5325ab2b72ee2f60d72d474809ad796c72b (patch)
tree18e45c3e51d6a694357a85555ff4492e044302fc
parent2342414f497ea6d76f91d109c28259aad5ec014c (diff)
parent1d3ca135d055dbda6c255227084296f3552b99a9 (diff)
downloadrust-f623e5325ab2b72ee2f60d72d474809ad796c72b.tar.gz
rust-f623e5325ab2b72ee2f60d72d474809ad796c72b.zip
Merge pull request #214 from sadlerap/minmax
simd: implement simd_fmin/fmax
-rw-r--r--failing-ui-tests.txt1
-rw-r--r--failing-ui-tests12.txt1
-rw-r--r--src/builder.rs32
-rw-r--r--src/intrinsic/simd.rs2
4 files changed, 35 insertions, 1 deletions
diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt
index 9e88859593d..fc6dcfc7bc7 100644
--- a/failing-ui-tests.txt
+++ b/failing-ui-tests.txt
@@ -32,7 +32,6 @@ src/test/ui/sepcomp/sepcomp-fns.rs
 src/test/ui/sepcomp/sepcomp-statics.rs
 src/test/ui/simd/generics.rs
 src/test/ui/simd/intrinsic/float-math-pass.rs
-src/test/ui/simd/intrinsic/float-minmax-pass.rs
 src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs
 src/test/ui/simd/intrinsic/generic-as.rs
 src/test/ui/simd/intrinsic/generic-bitmask-pass.rs
diff --git a/failing-ui-tests12.txt b/failing-ui-tests12.txt
index 2aab9c80f8f..e7952f52412 100644
--- a/failing-ui-tests12.txt
+++ b/failing-ui-tests12.txt
@@ -8,6 +8,7 @@ src/test/ui/packed/packed-struct-size.rs
 src/test/ui/packed/packed-struct-vec.rs
 src/test/ui/packed/packed-tuple-struct-layout.rs
 src/test/ui/simd/array-type.rs
+src/test/ui/simd/intrinsic/float-minmax-pass.rs
 src/test/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs
 src/test/ui/simd/intrinsic/generic-cast-pass.rs
 src/test/ui/simd/intrinsic/generic-cast-pointer-width.rs
diff --git a/src/builder.rs b/src/builder.rs
index d9b24b2dc35..52a4854aca3 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1505,6 +1505,34 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         })
     }
 
+    fn vector_extremum(&mut self, a: RValue<'gcc>, b: RValue<'gcc>, direction: ExtremumOperation) -> RValue<'gcc> {
+        let vector_type = a.get_type();
+
+        // mask out the NaNs in b and replace them with the corresponding lane in a, so when a and
+        // b get compared & spliced together, we get the numeric values instead of NaNs.
+        let b_nan_mask = self.context.new_comparison(None, ComparisonOp::NotEquals, b, b);
+        let mask_type = b_nan_mask.get_type();
+        let b_nan_mask_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, mask_type, b_nan_mask);
+        let a_cast = self.context.new_bitcast(None, a, mask_type);
+        let b_cast = self.context.new_bitcast(None, b, mask_type);
+        let res = (b_nan_mask & a_cast) | (b_nan_mask_inverted & b_cast);
+        let b = self.context.new_bitcast(None, res, vector_type);
+
+        // now do the actual comparison
+        let comparison_op = match direction {
+            ExtremumOperation::Min => ComparisonOp::LessThan,
+            ExtremumOperation::Max => ComparisonOp::GreaterThan,
+        };
+        let cmp = self.context.new_comparison(None, comparison_op, a, b);
+        let cmp_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, cmp.get_type(), cmp);
+        let res = (cmp & a_cast) | (cmp_inverted & res);
+        self.context.new_bitcast(None, res, vector_type)
+    }
+
+    pub fn vector_fmin(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.vector_extremum(a, b, ExtremumOperation::Min)
+    }
+
     #[cfg(feature="master")]
     pub fn vector_reduce_fmin(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
@@ -1525,6 +1553,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
+    pub fn vector_fmax(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.vector_extremum(a, b, ExtremumOperation::Max)
+    }
+
     #[cfg(feature="master")]
     pub fn vector_reduce_fmax(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs
index 8aed06869a9..36b5ab12b17 100644
--- a/src/intrinsic/simd.rs
+++ b/src/intrinsic/simd.rs
@@ -492,6 +492,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         simd_and: Uint, Int => and;
         simd_or: Uint, Int => or; // FIXME(antoyo): calling `or` might not work on vectors.
         simd_xor: Uint, Int => xor;
+        simd_fmin: Float => vector_fmin;
+        simd_fmax: Float => vector_fmax;
     }
 
     macro_rules! arith_unary {