Merge pull request #214 from sadlerap/minmax

simd: implement simd_fmin/fmax
This commit is contained in:
antoyo 2022-08-30 21:08:04 -04:00 committed by GitHub
commit f623e5325a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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 {