Skip to content

Commit

Permalink
Implement minimumf[32,64} and maximumf{32,64} intrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
Urgau committed Nov 17, 2021
1 parent 41301c3 commit 1d8aa13
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 1 deletion.
21 changes: 21 additions & 0 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,8 @@ symbols! {
masked,
match_beginning_vert,
match_default_bindings,
maximumf32,
maximumf64,
maxnumf32,
maxnumf64,
may_dangle,
Expand Down Expand Up @@ -837,6 +839,8 @@ symbols! {
min_const_unsafe_fn,
min_specialization,
min_type_alias_impl_trait,
minimumf32,
minimumf64,
minnumf32,
minnumf64,
mips_target_feature,
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_typeck/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
33 changes: 33 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 1d8aa13

Please sign in to comment.