Skip to content

Commit 57657e9

Browse files
authored
Rollup merge of rust-lang#140792 - Urgau:minimum-maximum-intrinsics, r=scottmcm,traviscross,tgross35
Use intrinsics for `{f16,f32,f64,f128}::{minimum,maximum}` operations This PR creates intrinsics for `{f16,f32,f64,f64}::{minimum,maximum}` operations. This wasn't done when those operations were added as the LLVM support was too weak but now that LLVM has libcalls for unsupported platforms we can finally use them. Cranelift and GCC[^1] support are partial, Cranelift doesn't support `f16` and `f128`, while GCC doesn't support `f16`. r? `@tgross35` try-job: aarch64-gnu try-job: dist-various-1 try-job: dist-various-2 [^1]: https://www.gnu.org/software///gnulib/manual/html_node/Functions-in-_003cmath_002eh_003e.html
2 parents ef7dcf4 + af36f33 commit 57657e9

File tree

5 files changed

+180
-84
lines changed

5 files changed

+180
-84
lines changed

core/src/intrinsics/mod.rs

Lines changed: 172 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3907,7 +3907,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
39073907
}
39083908
}
39093909

3910-
/// Returns the minimum of two `f16` values.
3910+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values.
39113911
///
39123912
/// Note that, unlike most intrinsics, this is safe to call;
39133913
/// it does not require an `unsafe` block.
@@ -3920,7 +3920,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
39203920
#[rustc_intrinsic]
39213921
pub const fn minnumf16(x: f16, y: f16) -> f16;
39223922

3923-
/// Returns the minimum of two `f32` values.
3923+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f32` values.
39243924
///
39253925
/// Note that, unlike most intrinsics, this is safe to call;
39263926
/// it does not require an `unsafe` block.
@@ -3934,7 +3934,7 @@ pub const fn minnumf16(x: f16, y: f16) -> f16;
39343934
#[rustc_intrinsic]
39353935
pub const fn minnumf32(x: f32, y: f32) -> f32;
39363936

3937-
/// Returns the minimum of two `f64` values.
3937+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f64` values.
39383938
///
39393939
/// Note that, unlike most intrinsics, this is safe to call;
39403940
/// it does not require an `unsafe` block.
@@ -3948,7 +3948,7 @@ pub const fn minnumf32(x: f32, y: f32) -> f32;
39483948
#[rustc_intrinsic]
39493949
pub const fn minnumf64(x: f64, y: f64) -> f64;
39503950

3951-
/// Returns the minimum of two `f128` values.
3951+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f128` values.
39523952
///
39533953
/// Note that, unlike most intrinsics, this is safe to call;
39543954
/// it does not require an `unsafe` block.
@@ -3961,7 +3961,91 @@ pub const fn minnumf64(x: f64, y: f64) -> f64;
39613961
#[rustc_intrinsic]
39623962
pub const fn minnumf128(x: f128, y: f128) -> f128;
39633963

3964-
/// Returns the maximum of two `f16` values.
3964+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f16` values.
3965+
///
3966+
/// Note that, unlike most intrinsics, this is safe to call;
3967+
/// it does not require an `unsafe` block.
3968+
/// Therefore, implementations must not require the user to uphold
3969+
/// any safety invariants.
3970+
#[rustc_nounwind]
3971+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
3972+
pub const fn minimumf16(x: f16, y: f16) -> f16 {
3973+
if x < y {
3974+
x
3975+
} else if y < x {
3976+
y
3977+
} else if x == y {
3978+
if x.is_sign_negative() && y.is_sign_positive() { x } else { y }
3979+
} else {
3980+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
3981+
x + y
3982+
}
3983+
}
3984+
3985+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f32` values.
3986+
///
3987+
/// Note that, unlike most intrinsics, this is safe to call;
3988+
/// it does not require an `unsafe` block.
3989+
/// Therefore, implementations must not require the user to uphold
3990+
/// any safety invariants.
3991+
#[rustc_nounwind]
3992+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
3993+
pub const fn minimumf32(x: f32, y: f32) -> f32 {
3994+
if x < y {
3995+
x
3996+
} else if y < x {
3997+
y
3998+
} else if x == y {
3999+
if x.is_sign_negative() && y.is_sign_positive() { x } else { y }
4000+
} else {
4001+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
4002+
x + y
4003+
}
4004+
}
4005+
4006+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f64` values.
4007+
///
4008+
/// Note that, unlike most intrinsics, this is safe to call;
4009+
/// it does not require an `unsafe` block.
4010+
/// Therefore, implementations must not require the user to uphold
4011+
/// any safety invariants.
4012+
#[rustc_nounwind]
4013+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4014+
pub const fn minimumf64(x: f64, y: f64) -> f64 {
4015+
if x < y {
4016+
x
4017+
} else if y < x {
4018+
y
4019+
} else if x == y {
4020+
if x.is_sign_negative() && y.is_sign_positive() { x } else { y }
4021+
} else {
4022+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
4023+
x + y
4024+
}
4025+
}
4026+
4027+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f128` values.
4028+
///
4029+
/// Note that, unlike most intrinsics, this is safe to call;
4030+
/// it does not require an `unsafe` block.
4031+
/// Therefore, implementations must not require the user to uphold
4032+
/// any safety invariants.
4033+
#[rustc_nounwind]
4034+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4035+
pub const fn minimumf128(x: f128, y: f128) -> f128 {
4036+
if x < y {
4037+
x
4038+
} else if y < x {
4039+
y
4040+
} else if x == y {
4041+
if x.is_sign_negative() && y.is_sign_positive() { x } else { y }
4042+
} else {
4043+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
4044+
x + y
4045+
}
4046+
}
4047+
4048+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f16` values.
39654049
///
39664050
/// Note that, unlike most intrinsics, this is safe to call;
39674051
/// it does not require an `unsafe` block.
@@ -3974,7 +4058,7 @@ pub const fn minnumf128(x: f128, y: f128) -> f128;
39744058
#[rustc_intrinsic]
39754059
pub const fn maxnumf16(x: f16, y: f16) -> f16;
39764060

3977-
/// Returns the maximum of two `f32` values.
4061+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f32` values.
39784062
///
39794063
/// Note that, unlike most intrinsics, this is safe to call;
39804064
/// it does not require an `unsafe` block.
@@ -3988,7 +4072,7 @@ pub const fn maxnumf16(x: f16, y: f16) -> f16;
39884072
#[rustc_intrinsic]
39894073
pub const fn maxnumf32(x: f32, y: f32) -> f32;
39904074

3991-
/// Returns the maximum of two `f64` values.
4075+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f64` values.
39924076
///
39934077
/// Note that, unlike most intrinsics, this is safe to call;
39944078
/// it does not require an `unsafe` block.
@@ -4002,7 +4086,7 @@ pub const fn maxnumf32(x: f32, y: f32) -> f32;
40024086
#[rustc_intrinsic]
40034087
pub const fn maxnumf64(x: f64, y: f64) -> f64;
40044088

4005-
/// Returns the maximum of two `f128` values.
4089+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f128` values.
40064090
///
40074091
/// Note that, unlike most intrinsics, this is safe to call;
40084092
/// it does not require an `unsafe` block.
@@ -4015,6 +4099,86 @@ pub const fn maxnumf64(x: f64, y: f64) -> f64;
40154099
#[rustc_intrinsic]
40164100
pub const fn maxnumf128(x: f128, y: f128) -> f128;
40174101

4102+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f16` values.
4103+
///
4104+
/// Note that, unlike most intrinsics, this is safe to call;
4105+
/// it does not require an `unsafe` block.
4106+
/// Therefore, implementations must not require the user to uphold
4107+
/// any safety invariants.
4108+
#[rustc_nounwind]
4109+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4110+
pub const fn maximumf16(x: f16, y: f16) -> f16 {
4111+
if x > y {
4112+
x
4113+
} else if y > x {
4114+
y
4115+
} else if x == y {
4116+
if x.is_sign_positive() && y.is_sign_negative() { x } else { y }
4117+
} else {
4118+
x + y
4119+
}
4120+
}
4121+
4122+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f32` values.
4123+
///
4124+
/// Note that, unlike most intrinsics, this is safe to call;
4125+
/// it does not require an `unsafe` block.
4126+
/// Therefore, implementations must not require the user to uphold
4127+
/// any safety invariants.
4128+
#[rustc_nounwind]
4129+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4130+
pub const fn maximumf32(x: f32, y: f32) -> f32 {
4131+
if x > y {
4132+
x
4133+
} else if y > x {
4134+
y
4135+
} else if x == y {
4136+
if x.is_sign_positive() && y.is_sign_negative() { x } else { y }
4137+
} else {
4138+
x + y
4139+
}
4140+
}
4141+
4142+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f64` values.
4143+
///
4144+
/// Note that, unlike most intrinsics, this is safe to call;
4145+
/// it does not require an `unsafe` block.
4146+
/// Therefore, implementations must not require the user to uphold
4147+
/// any safety invariants.
4148+
#[rustc_nounwind]
4149+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4150+
pub const fn maximumf64(x: f64, y: f64) -> f64 {
4151+
if x > y {
4152+
x
4153+
} else if y > x {
4154+
y
4155+
} else if x == y {
4156+
if x.is_sign_positive() && y.is_sign_negative() { x } else { y }
4157+
} else {
4158+
x + y
4159+
}
4160+
}
4161+
4162+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f128` values.
4163+
///
4164+
/// Note that, unlike most intrinsics, this is safe to call;
4165+
/// it does not require an `unsafe` block.
4166+
/// Therefore, implementations must not require the user to uphold
4167+
/// any safety invariants.
4168+
#[rustc_nounwind]
4169+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
4170+
pub const fn maximumf128(x: f128, y: f128) -> f128 {
4171+
if x > y {
4172+
x
4173+
} else if y > x {
4174+
y
4175+
} else if x == y {
4176+
if x.is_sign_positive() && y.is_sign_negative() { x } else { y }
4177+
} else {
4178+
x + y
4179+
}
4180+
}
4181+
40184182
/// Returns the absolute value of an `f16`.
40194183
///
40204184
/// The stabilized version of this intrinsic is

core/src/num/f128.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -757,15 +757,7 @@ impl f128 {
757757
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
758758
#[must_use = "this returns the result of the comparison, without modifying either input"]
759759
pub const fn maximum(self, other: f128) -> f128 {
760-
if self > other {
761-
self
762-
} else if other > self {
763-
other
764-
} else if self == other {
765-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
766-
} else {
767-
self + other
768-
}
760+
intrinsics::maximumf128(self, other)
769761
}
770762

771763
/// Returns the minimum of the two numbers, propagating NaN.
@@ -798,16 +790,7 @@ impl f128 {
798790
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
799791
#[must_use = "this returns the result of the comparison, without modifying either input"]
800792
pub const fn minimum(self, other: f128) -> f128 {
801-
if self < other {
802-
self
803-
} else if other < self {
804-
other
805-
} else if self == other {
806-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
807-
} else {
808-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
809-
self + other
810-
}
793+
intrinsics::minimumf128(self, other)
811794
}
812795

813796
/// Calculates the midpoint (average) between `self` and `rhs`.

core/src/num/f16.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -746,15 +746,7 @@ impl f16 {
746746
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
747747
#[must_use = "this returns the result of the comparison, without modifying either input"]
748748
pub const fn maximum(self, other: f16) -> f16 {
749-
if self > other {
750-
self
751-
} else if other > self {
752-
other
753-
} else if self == other {
754-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
755-
} else {
756-
self + other
757-
}
749+
intrinsics::maximumf16(self, other)
758750
}
759751

760752
/// Returns the minimum of the two numbers, propagating NaN.
@@ -786,16 +778,7 @@ impl f16 {
786778
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
787779
#[must_use = "this returns the result of the comparison, without modifying either input"]
788780
pub const fn minimum(self, other: f16) -> f16 {
789-
if self < other {
790-
self
791-
} else if other < self {
792-
other
793-
} else if self == other {
794-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
795-
} else {
796-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
797-
self + other
798-
}
781+
intrinsics::minimumf16(self, other)
799782
}
800783

801784
/// Calculates the midpoint (average) between `self` and `rhs`.

core/src/num/f32.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -944,15 +944,7 @@ impl f32 {
944944
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
945945
#[inline]
946946
pub const fn maximum(self, other: f32) -> f32 {
947-
if self > other {
948-
self
949-
} else if other > self {
950-
other
951-
} else if self == other {
952-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
953-
} else {
954-
self + other
955-
}
947+
intrinsics::maximumf32(self, other)
956948
}
957949

958950
/// Returns the minimum of the two numbers, propagating NaN.
@@ -979,16 +971,7 @@ impl f32 {
979971
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
980972
#[inline]
981973
pub const fn minimum(self, other: f32) -> f32 {
982-
if self < other {
983-
self
984-
} else if other < self {
985-
other
986-
} else if self == other {
987-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
988-
} else {
989-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
990-
self + other
991-
}
974+
intrinsics::minimumf32(self, other)
992975
}
993976

994977
/// Calculates the midpoint (average) between `self` and `rhs`.

core/src/num/f64.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -962,15 +962,7 @@ impl f64 {
962962
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
963963
#[inline]
964964
pub const fn maximum(self, other: f64) -> f64 {
965-
if self > other {
966-
self
967-
} else if other > self {
968-
other
969-
} else if self == other {
970-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
971-
} else {
972-
self + other
973-
}
965+
intrinsics::maximumf64(self, other)
974966
}
975967

976968
/// Returns the minimum of the two numbers, propagating NaN.
@@ -997,16 +989,7 @@ impl f64 {
997989
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
998990
#[inline]
999991
pub const fn minimum(self, other: f64) -> f64 {
1000-
if self < other {
1001-
self
1002-
} else if other < self {
1003-
other
1004-
} else if self == other {
1005-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
1006-
} else {
1007-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
1008-
self + other
1009-
}
992+
intrinsics::minimumf64(self, other)
1010993
}
1011994

1012995
/// Calculates the midpoint (average) between `self` and `rhs`.

0 commit comments

Comments
 (0)