diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 313b62c5770b6..c4e17533d46e8 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1064,6 +1064,27 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( ret.write_cvalue(fx, val); }; + minimumf32, (v a, v b) { + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + }; + minimumf64, (v a, v b) { + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + }; + maximumf32, (v a, v b) { + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + }; + maximumf64, (v a, v b) { + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + }; + kw.Try, (v f, v data, v _catch_fn) { // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 64bd586662d38..04450370dcbe9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -53,6 +53,13 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) -> sym::minnumf64 => "fmin", sym::maxnumf32 => "fmaxf", sym::maxnumf64 => "fmax", + // FIXME: GCC currently doens't seems to have builtins that propagate NaN + // as required by the {min,max}imum instrinsics. For the mean time + // use the builtins that doens't propagate the NaN + sym::minimumf32 => "fminf", + sym::minimumf64 => "fmin", + sym::maximumf32 => "fmaxf", + sym::maximumf64 => "fmax", sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", sym::floorf32 => "floorf", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1dba264a9614a..ed4dc0a1292ae 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -640,6 +640,11 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32); ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64); + ifn!("llvm.minimum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.minimum.f64", fn(t_f64, t_f64) -> t_f64); + ifn!("llvm.maximum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.maximum.f64", fn(t_f64, t_f64) -> t_f64); + ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 924bb803b368f..0baea3f61197d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -55,6 +55,10 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<(&'ll T sym::minnumf64 => "llvm.minnum.f64", sym::maxnumf32 => "llvm.maxnum.f32", sym::maxnumf64 => "llvm.maxnum.f64", + sym::minimumf32 => "llvm.minimum.f32", + sym::minimumf64 => "llvm.minimum.f64", + sym::maximumf32 => "llvm.maximum.f32", + sym::maximumf64 => "llvm.maximum.f64", sym::copysignf32 => "llvm.copysign.f32", sym::copysignf64 => "llvm.copysign.f64", sym::floorf32 => "llvm.floor.f32", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 99fa9f000944d..163e940d4b69d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -810,6 +810,8 @@ symbols! { masked, match_beginning_vert, match_default_bindings, + maximumf32, + maximumf64, maxnumf32, maxnumf64, may_dangle, @@ -837,6 +839,8 @@ symbols! { min_const_unsafe_fn, min_specialization, min_type_alias_impl_trait, + minimumf32, + minimumf64, minnumf32, minnumf64, mips_target_feature, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 6314f2aba4efe..aa64ee363d85c 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -98,8 +98,12 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { | sym::minnumf32 | sym::minnumf64 | sym::maxnumf32 - | sym::rustc_peek | sym::maxnumf64 + | sym::minimumf32 + | sym::minimumf64 + | sym::maximumf32 + | sym::maximumf64 + | sym::rustc_peek | sym::type_name | sym::forget | sym::black_box @@ -256,6 +260,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::minimumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::minimumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::maximumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::maximumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32), diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 0f57fb5b14180..d34e3dc9f4cb6 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1406,6 +1406,39 @@ extern "rust-intrinsic" { /// [`f64::max`] pub fn maxnumf64(x: f64, y: f64) -> f64; + /// Returns the minimum of two `f32` values. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + #[cfg(not(bootstrap))] + pub fn minimumf32(x: f32, y: f32) -> f32; + /// Returns the minimum of two `f64` values. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + #[cfg(not(bootstrap))] + pub fn minimumf64(x: f64, y: f64) -> f64; + /// Returns the maximum of two `f32` values. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + #[cfg(not(bootstrap))] + pub fn maximumf32(x: f32, y: f32) -> f32; + /// Returns the maximum of two `f64` values. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + #[cfg(not(bootstrap))] + pub fn maximumf64(x: f64, y: f64) -> f64; + /// Copies the sign from `y` to `x` for `f32` values. /// /// The stabilized version of this intrinsic is