diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs index b7491b7e522f3..206c56e887c7d 100644 --- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs +++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs @@ -33,24 +33,24 @@ fn main() { let n = f32x4([nan, nan, nan, nan]); unsafe { - let min0 = simd_fmin(x, y); - let min1 = simd_fmin(y, x); + let min0 = simd_minimum_number_nsz(x, y); + let min1 = simd_minimum_number_nsz(y, x); assert_eq!(min0.into_array(), min1.into_array()); let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0.into_array(), e.into_array()); - let minn = simd_fmin(x, n); + let minn = simd_minimum_number_nsz(x, n); assert_eq!(minn.into_array(), x.into_array()); - let minn = simd_fmin(y, n); + let minn = simd_minimum_number_nsz(y, n); assert_eq!(minn.into_array(), y.into_array()); - let max0 = simd_fmax(x, y); - let max1 = simd_fmax(y, x); + let max0 = simd_maximum_number_nsz(x, y); + let max1 = simd_maximum_number_nsz(y, x); assert_eq!(max0.into_array(), max1.into_array()); let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0.into_array(), e.into_array()); - let maxn = simd_fmax(x, n); + let maxn = simd_maximum_number_nsz(x, n); assert_eq!(maxn.into_array(), x.into_array()); - let maxn = simd_fmax(y, n); + let maxn = simd_maximum_number_nsz(y, n); assert_eq!(maxn.into_array(), y.into_array()); } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 200cedf0f6ae0..cc2311a67b5d5 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -493,7 +493,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } } - sym::simd_fmin | sym::simd_fmax => { + sym::simd_minimum_number_nsz | sym::simd_maximum_number_nsz => { intrinsic_args!(fx, args => (x, y); intrinsic); if !x.layout().ty.is_simd() { @@ -508,8 +508,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!("{:?}", lane_ty), } match intrinsic { - sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane), - sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane), + sym::simd_minimum_number_nsz => { + crate::num::codegen_float_min(fx, x_lane, y_lane) + } + sym::simd_maximum_number_nsz => { + crate::num::codegen_float_max(fx, x_lane, y_lane) + } _ => unreachable!(), } }); diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index 0459644e16aa7..e583f3f2f754a 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -500,8 +500,8 @@ fn codegen_ptr_binop<'tcx>( // In Rust floating point min and max don't propagate NaN (not even SNaN). In Cranelift they do // however. For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for -// `minnumf*` and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by -// comparing a float against itself. Only in case of NaN is it not equal to itself. +// `minimum_number_nsz` and `a.is_nan() ? b : (a <= b ? b : a)` for `maximum_number_nsz`. NaN checks +// are done by comparing a float against itself. Only in case of NaN is it not equal to itself. pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift `fcmp` once // `f16`/`f128` backend lowerings have been added to Cranelift. diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 6add7f05c2abd..3eb0fd95284a1 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -2278,6 +2278,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }) } + /// Emits a SIMD min/max operation for floats. The semantics for each lane are: if one + /// side is NaN (QNaN or SNaN), the other side is returned. fn vector_extremum( &mut self, a: RValue<'gcc>, @@ -2286,8 +2288,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ) -> 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. + // Mask out the NaNs (both QNaN and SNaN) 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(self.location, ComparisonOp::NotEquals, b, b); let mask_type = b_nan_mask.get_type(); let b_nan_mask_inverted = @@ -2309,7 +2312,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_bitcast(self.location, res, vector_type) } - pub fn vector_fmin(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + pub fn vector_minimum_number_nsz(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { self.vector_extremum(a, b, ExtremumOperation::Min) } @@ -2341,7 +2344,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { unimplemented!(); } - pub fn vector_fmax(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + pub fn vector_maximum_number_nsz(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { self.vector_extremum(a, b, ExtremumOperation::Max) } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 1263b2285a8d0..06254fcb180b2 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -1222,8 +1222,8 @@ pub fn generic_simd_intrinsic<'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; + simd_minimum_number_nsz: Float => vector_minimum_number_nsz; + simd_maximum_number_nsz: Float => vector_maximum_number_nsz; } macro_rules! arith_unary { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 2d91caf40f3c9..f3508c10d1f61 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1605,12 +1605,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { *self = Self::build(self.cx, next_bb); } - pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.call_intrinsic("llvm.minnum", &[self.val_ty(lhs)], &[lhs, rhs]) + pub(crate) fn minimum_number_nsz(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + let call = self.call_intrinsic("llvm.minimumnum", &[self.val_ty(lhs)], &[lhs, rhs]); + unsafe { llvm::LLVMRustSetNoSignedZeros(call) }; + call } - pub(crate) fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { - self.call_intrinsic("llvm.maxnum", &[self.val_ty(lhs)], &[lhs, rhs]) + pub(crate) fn maximum_number_nsz(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + let call = self.call_intrinsic("llvm.maximumnum", &[self.val_ty(lhs)], &[lhs, rhs]); + unsafe { llvm::LLVMRustSetNoSignedZeros(call) }; + call } pub(crate) fn insert_element( diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cc6ecee60b0e4..8bf2be52ce887 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -2770,8 +2770,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>( simd_and: Uint, Int => and; simd_or: Uint, Int => or; simd_xor: Uint, Int => xor; - simd_fmax: Float => maxnum; - simd_fmin: Float => minnum; + simd_maximum_number_nsz: Float => maximum_number_nsz; + simd_minimum_number_nsz: Float => minimum_number_nsz; } macro_rules! arith_unary { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index c47c512025c08..d6cfc559e0df4 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -174,8 +174,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | sym::simd_le | sym::simd_gt | sym::simd_ge - | sym::simd_fmax - | sym::simd_fmin + | sym::simd_maximum_number_nsz + | sym::simd_minimum_number_nsz | sym::simd_saturating_add | sym::simd_saturating_sub | sym::simd_arith_offset => { @@ -211,8 +211,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::simd_le => Op::MirOp(BinOp::Le), sym::simd_gt => Op::MirOp(BinOp::Gt), sym::simd_ge => Op::MirOp(BinOp::Ge), - sym::simd_fmax => Op::FMinMax(MinMax::MaximumNumberNsz), - sym::simd_fmin => Op::FMinMax(MinMax::MinimumNumberNsz), + sym::simd_maximum_number_nsz => Op::FMinMax(MinMax::MaximumNumberNsz), + sym::simd_minimum_number_nsz => Op::FMinMax(MinMax::MinimumNumberNsz), sym::simd_saturating_add => Op::SaturatingOp(BinOp::Add), sym::simd_saturating_sub => Op::SaturatingOp(BinOp::Sub), sym::simd_arith_offset => Op::WrappingOffset, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 47420997a509a..3f98699208749 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -726,8 +726,8 @@ pub(crate) fn check_intrinsic_type( | sym::simd_and | sym::simd_or | sym::simd_xor - | sym::simd_fmin - | sym::simd_fmax + | sym::simd_minimum_number_nsz + | sym::simd_maximum_number_nsz | sym::simd_saturating_add | sym::simd_saturating_sub | sym::simd_carryless_mul => (1, 0, vec![param(0), param(0)], param(0)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 286fea7d90505..3b10b8bcda2d8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1850,8 +1850,6 @@ symbols! { simd_flog10, simd_floor, simd_fma, - simd_fmax, - simd_fmin, simd_fsin, simd_fsqrt, simd_funnel_shl, @@ -1865,6 +1863,8 @@ symbols! { simd_lt, simd_masked_load, simd_masked_store, + simd_maximum_number_nsz, + simd_minimum_number_nsz, simd_mul, simd_ne, simd_neg, diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 5fb2102c319e2..e5a53b3a25d36 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -250,19 +250,27 @@ pub const unsafe fn simd_fabs(x: T) -> T; /// /// `T` must be a vector of floating-point primitive types. /// -/// Follows IEEE-754 `minNum` semantics. +/// This behaves like IEEE 754-2019 minimumNumber, *except* that it does not order signed +/// zeros deterministically. In particular, for each vector lane: +/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If +/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0` +/// and `-0.0`), either input may be returned non-deterministically. #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn simd_fmin(x: T, y: T) -> T; +pub const unsafe fn simd_minimum_number_nsz(x: T, y: T) -> T; /// Returns the maximum of two vectors, elementwise. /// /// `T` must be a vector of floating-point primitive types. /// -/// Follows IEEE-754 `maxNum` semantics. +/// This behaves like IEEE 754-2019 maximumNumber, *except* that it does not order signed +/// zeros deterministically. In particular, for each vector lane: +/// If one of the arguments is NaN (quiet or signaling), then the other argument is returned. If +/// both arguments are NaN, returns NaN. If the inputs compare equal (such as for the case of `+0.0` +/// and `-0.0`), either input may be returned non-deterministically. #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn simd_fmax(x: T, y: T) -> T; +pub const unsafe fn simd_maximum_number_nsz(x: T, y: T) -> T; /// Tests elementwise equality of two vectors. /// diff --git a/library/portable-simd/crates/core_simd/src/simd/num/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs index efd7c2469512b..175cbce4f58be 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/float.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs @@ -385,13 +385,13 @@ macro_rules! impl_trait { #[inline] fn simd_min(self, other: Self) -> Self { // Safety: `self` and `other` are float vectors - unsafe { core::intrinsics::simd::simd_fmin(self, other) } + unsafe { core::intrinsics::simd::simd_minimum_number_nsz(self, other) } } #[inline] fn simd_max(self, other: Self) -> Self { // Safety: `self` and `other` are floating point vectors - unsafe { core::intrinsics::simd::simd_fmax(self, other) } + unsafe { core::intrinsics::simd::simd_maximum_number_nsz(self, other) } } #[inline] diff --git a/library/stdarch/crates/core_arch/src/nvptx/packed.rs b/library/stdarch/crates/core_arch/src/nvptx/packed.rs index 856aeea4b686c..1c7e81268fc99 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/packed.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/packed.rs @@ -99,7 +99,7 @@ pub unsafe fn f16x2_neg(a: f16x2) -> f16x2 { #[cfg_attr(test, assert_instr(min.f16x2))] #[unstable(feature = "stdarch_nvptx", issue = "111199")] pub unsafe fn f16x2_min(a: f16x2, b: f16x2) -> f16x2 { - simd_fmin(a, b) + simd_minimum_number_nsz(a, b) } /// Find the minimum of two values, NaNs pass through. @@ -123,7 +123,7 @@ pub unsafe fn f16x2_min_nan(a: f16x2, b: f16x2) -> f16x2 { #[cfg_attr(test, assert_instr(max.f16x2))] #[unstable(feature = "stdarch_nvptx", issue = "111199")] pub unsafe fn f16x2_max(a: f16x2, b: f16x2) -> f16x2 { - simd_fmax(a, b) + simd_maximum_number_nsz(a, b) } /// Find the maximum of two values, NaNs pass through. diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index 3f7781cc7dc4c..9183eabd530ca 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -208,7 +208,7 @@ pub fn _mm_min_ss(a: __m128, b: __m128) -> __m128 { #[cfg_attr(test, assert_instr(minps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_min_ps(a: __m128, b: __m128) -> __m128 { - // See the `test_mm_min_ps` test why this can't be implemented using `simd_fmin`. + // See the `test_mm_min_ps` test why this can't be implemented using `simd_minimum_number_nsz`. unsafe { minps(a, b) } } @@ -234,7 +234,7 @@ pub fn _mm_max_ss(a: __m128, b: __m128) -> __m128 { #[cfg_attr(test, assert_instr(maxps))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_max_ps(a: __m128, b: __m128) -> __m128 { - // See the `test_mm_min_ps` test why this can't be implemented using `simd_fmax`. + // See the `test_mm_min_ps` test why this can't be implemented using `simd_maximum_number_nsz`. unsafe { maxps(a, b) } } @@ -2227,11 +2227,11 @@ mod tests { let r = _mm_min_ps(a, b); assert_eq_m128(r, _mm_setr_ps(-100.0, 5.0, 0.0, -10.0)); - // `_mm_min_ps` can **not** be implemented using the `simd_min` rust intrinsic. `simd_min` - // is lowered by the llvm codegen backend to `llvm.minnum.v*` llvm intrinsic. This intrinsic - // doesn't specify how -0.0 is handled. Unfortunately it happens to behave different from - // the `minps` x86 instruction on x86. The `llvm.minnum.v*` llvm intrinsic equals - // `r1` to `a` and `r2` to `b`. + // `_mm_min_ps` can **not** be implemented using the `simd_minimum_number_nsz` rust + // intrinsic. That intrinsic is lowered by the llvm codegen backend to `llvm.minimumnum.v*` + // llvm intrinsic with the `nsz` attribute. The `nsz` attribute means -0.0 is handled + // non-deterministically. The `minps` x86 instruction however has a deterministic semantics + // for signed zeros. let a = _mm_setr_ps(-0.0, 0.0, 0.0, 0.0); let b = _mm_setr_ps(0.0, 0.0, 0.0, 0.0); let r1 = _mm_min_ps(a, b).as_f32x4().to_bits(); diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 6b39c2db3587a..4ec5a7e9c2090 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -513,10 +513,10 @@ fn test_simd() { F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0]) }); check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || { - F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0]) + F32::from(unsafe { simd_minimum_number_nsz(f32x4::splat(nan), f32x4::splat(nan)) }[0]) }); check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || { - F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0]) + F32::from(unsafe { simd_maximum_number_nsz(f32x4::splat(nan), f32x4::splat(nan)) }[0]) }); check_all_outcomes([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)], || { F32::from(unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0]) diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index b4fd8e2165336..1e86c458ac21c 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -90,11 +90,11 @@ fn simd_ops_f16() { assert_eq!(simd_rem(a, b), f16x4::from_array([0.0, 0.0, 1.0, 2.0])); assert_eq!(simd_fabs(b), f16x4::from_array([1.0, 2.0, 3.0, 4.0])); assert_eq!( - simd_fmax(a, simd_mul(b, f16x4::splat(4.0))), + simd_maximum_number_nsz(a, simd_mul(b, f16x4::splat(4.0))), f16x4::from_array([10.0, 10.0, 12.0, 10.0]) ); assert_eq!( - simd_fmin(a, simd_mul(b, f16x4::splat(4.0))), + simd_minimum_number_nsz(a, simd_mul(b, f16x4::splat(4.0))), f16x4::from_array([4.0, 8.0, 10.0, -16.0]) ); @@ -134,13 +134,13 @@ fn simd_ops_f16() { assert_eq!(simd_reduce_min(b), -4.0f16); assert_eq!( - simd_fmax(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), + simd_maximum_number_nsz(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), f16x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_max(f16x2::from_array([0.0, f16::NAN])), 0.0f16); assert_eq!(simd_reduce_max(f16x2::from_array([f16::NAN, 0.0])), 0.0f16); assert_eq!( - simd_fmin(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), + simd_minimum_number_nsz(f16x2::from_array([0.0, f16::NAN]), f16x2::from_array([f16::NAN, 0.0])), f16x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_min(f16x2::from_array([0.0, f16::NAN])), 0.0f16); @@ -304,11 +304,11 @@ fn simd_ops_f128() { assert_eq!(simd_rem(a, b), f128x4::from_array([0.0, 0.0, 1.0, 2.0])); assert_eq!(simd_fabs(b), f128x4::from_array([1.0, 2.0, 3.0, 4.0])); assert_eq!( - simd_fmax(a, simd_mul(b, f128x4::splat(4.0))), + simd_maximum_number_nsz(a, simd_mul(b, f128x4::splat(4.0))), f128x4::from_array([10.0, 10.0, 12.0, 10.0]) ); assert_eq!( - simd_fmin(a, simd_mul(b, f128x4::splat(4.0))), + simd_minimum_number_nsz(a, simd_mul(b, f128x4::splat(4.0))), f128x4::from_array([4.0, 8.0, 10.0, -16.0]) ); @@ -348,13 +348,13 @@ fn simd_ops_f128() { assert_eq!(simd_reduce_min(b), -4.0f128); assert_eq!( - simd_fmax(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), + simd_maximum_number_nsz(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), f128x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_max(f128x2::from_array([0.0, f128::NAN])), 0.0f128); assert_eq!(simd_reduce_max(f128x2::from_array([f128::NAN, 0.0])), 0.0f128); assert_eq!( - simd_fmin(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), + simd_minimum_number_nsz(f128x2::from_array([0.0, f128::NAN]), f128x2::from_array([f128::NAN, 0.0])), f128x2::from_array([0.0, 0.0]) ); assert_eq!(simd_reduce_min(f128x2::from_array([0.0, f128::NAN])), 0.0f128); diff --git a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-float-minmax.rs b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-float-minmax.rs index 8dd464a1bffb6..94f7e160f8daf 100644 --- a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -8,18 +8,18 @@ mod minisimd; use minisimd::*; -use std::intrinsics::simd::{simd_fmax, simd_fmin}; +use std::intrinsics::simd::*; // CHECK-LABEL: @fmin #[no_mangle] pub unsafe fn fmin(a: f32x4, b: f32x4) -> f32x4 { - // CHECK: call <4 x float> @llvm.minnum.v4f32 - simd_fmin(a, b) + // CHECK: call nsz <4 x float> @llvm.minimumnum.v4f32 + simd_minimum_number_nsz(a, b) } // CHECK-LABEL: @fmax #[no_mangle] pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 { - // CHECK: call <4 x float> @llvm.maxnum.v4f32 - simd_fmax(a, b) + // CHECK: call nsz <4 x float> @llvm.maximumnum.v4f32 + simd_maximum_number_nsz(a, b) } diff --git a/tests/ui/simd/intrinsic/float-minmax-pass.rs b/tests/ui/simd/intrinsic/float-minmax-pass.rs index d9dc291de63d4..8ef5d85385a41 100644 --- a/tests/ui/simd/intrinsic/float-minmax-pass.rs +++ b/tests/ui/simd/intrinsic/float-minmax-pass.rs @@ -1,8 +1,8 @@ //@ run-pass //@ ignore-emscripten -//@ compile-flags: --cfg minisimd_const +//@ compile-flags: --cfg minisimd_const -O -// Test that the simd_f{min,max} intrinsics produce the correct results. +// Test that the simd_{min,max}imum_number_nsz intrinsics produce the correct results. #![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)] #![allow(non_camel_case_types)] @@ -12,41 +12,38 @@ mod minisimd; use minisimd::*; use std::intrinsics::simd::*; +use std::hint::black_box; const fn minmax() { let x = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); let y = f32x4::from_array([2.0, 1.0, 4.0, 3.0]); - #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; - // MIPS hardware except MIPS R6 treats f32::NAN as SNAN. Clear the signaling bit. - // See https://github.com/rust-lang/rust/issues/52746. // The "-1" works because we rely on `NAN` to have an all-0 payload, so the signaling // bit is the least significant non-zero bit. - #[cfg(any(target_arch = "mips", target_arch = "mips64"))] - let nan = f32::from_bits(f32::NAN.to_bits() - 1); + let snan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4::from_array([nan, nan, nan, nan]); + let n = f32x4::from_array([nan, nan, snan, snan]); unsafe { - let min0 = simd_fmin(x, y); - let min1 = simd_fmin(y, x); + let min0 = simd_minimum_number_nsz(x, y); + let min1 = simd_minimum_number_nsz(y, black_box(x)); assert_eq!(min0, min1); let e = f32x4::from_array([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); - let minn = simd_fmin(x, n); + let minn = simd_minimum_number_nsz(x, n); assert_eq!(minn, x); - let minn = simd_fmin(y, n); + let minn = simd_minimum_number_nsz(black_box(y), n); assert_eq!(minn, y); - let max0 = simd_fmax(x, y); - let max1 = simd_fmax(y, x); + let max0 = simd_maximum_number_nsz(x, y); + let max1 = simd_maximum_number_nsz(y, black_box(x)); assert_eq!(max0, max1); let e = f32x4::from_array([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); - let maxn = simd_fmax(x, n); + let maxn = simd_maximum_number_nsz(x, n); assert_eq!(maxn, x); - let maxn = simd_fmax(y, n); + let maxn = simd_maximum_number_nsz(n, black_box(y)); assert_eq!(maxn, y); } }