1
Fork 0

intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic

This commit is contained in:
Ralf Jung 2025-02-04 15:15:28 +01:00
parent 019fc4de2f
commit 04e7a10af6
13 changed files with 111 additions and 208 deletions

View file

@ -340,14 +340,10 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64),
sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32),
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64),
sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32),
sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64),
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32),
sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64),
sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32),
sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64),
sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32),
sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32),
@ -399,8 +395,8 @@ fn codegen_float_intrinsic_call<'tcx>(
| sym::ceilf64 | sym::ceilf64
| sym::truncf32 | sym::truncf32
| sym::truncf64 | sym::truncf64
| sym::nearbyintf32 | sym::round_ties_even_f32
| sym::nearbyintf64 | sym::round_ties_even_f64
| sym::sqrtf32 | sym::sqrtf32
| sym::sqrtf64 => { | sym::sqrtf64 => {
let val = match intrinsic { let val = match intrinsic {
@ -408,7 +404,9 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]), sym::round_ties_even_f32 | sym::round_ties_even_f64 => {
fx.bcx.ins().nearest(args[0])
}
sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]),
_ => unreachable!(), _ => unreachable!(),
}; };

View file

@ -84,14 +84,11 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
sym::ceilf64 => "ceil", sym::ceilf64 => "ceil",
sym::truncf32 => "truncf", sym::truncf32 => "truncf",
sym::truncf64 => "trunc", sym::truncf64 => "trunc",
sym::rintf32 => "rintf", // We match the LLVM backend and lower this to `rint`.
sym::rintf64 => "rint", sym::round_ties_even_f32 => "rintf",
sym::nearbyintf32 => "nearbyintf", sym::round_ties_even_f64 => "rint",
sym::nearbyintf64 => "nearbyint",
sym::roundf32 => "roundf", sym::roundf32 => "roundf",
sym::roundf64 => "round", sym::roundf64 => "round",
sym::roundevenf32 => "roundevenf",
sym::roundevenf64 => "roundeven",
sym::abort => "abort", sym::abort => "abort",
_ => return None, _ => return None,
}; };

View file

@ -126,15 +126,14 @@ fn get_simple_intrinsic<'ll>(
sym::truncf64 => "llvm.trunc.f64", sym::truncf64 => "llvm.trunc.f64",
sym::truncf128 => "llvm.trunc.f128", sym::truncf128 => "llvm.trunc.f128",
sym::rintf16 => "llvm.rint.f16", // We could use any of `rint`, `nearbyint`, or `roundeven`
sym::rintf32 => "llvm.rint.f32", // for this -- they are all identical in semantics when
sym::rintf64 => "llvm.rint.f64", // assuming the default FP environment.
sym::rintf128 => "llvm.rint.f128", // `rint` is what we used for $forever.
sym::round_ties_even_f16 => "llvm.rint.f16",
sym::nearbyintf16 => "llvm.nearbyint.f16", sym::round_ties_even_f32 => "llvm.rint.f32",
sym::nearbyintf32 => "llvm.nearbyint.f32", sym::round_ties_even_f64 => "llvm.rint.f64",
sym::nearbyintf64 => "llvm.nearbyint.f64", sym::round_ties_even_f128 => "llvm.rint.f128",
sym::nearbyintf128 => "llvm.nearbyint.f128",
sym::roundf16 => "llvm.round.f16", sym::roundf16 => "llvm.round.f16",
sym::roundf32 => "llvm.round.f32", sym::roundf32 => "llvm.round.f32",
@ -143,11 +142,6 @@ fn get_simple_intrinsic<'ll>(
sym::ptr_mask => "llvm.ptrmask", sym::ptr_mask => "llvm.ptrmask",
sym::roundevenf16 => "llvm.roundeven.f16",
sym::roundevenf32 => "llvm.roundeven.f32",
sym::roundevenf64 => "llvm.roundeven.f64",
sym::roundevenf128 => "llvm.roundeven.f128",
_ => return None, _ => return None,
}; };
Some(cx.get_intrinsic(llvm_name)) Some(cx.get_intrinsic(llvm_name))

View file

@ -398,26 +398,16 @@ pub fn check_intrinsic_type(
sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::rintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::round_ties_even_f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::rintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::round_ties_even_f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::rintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::round_ties_even_f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::rintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), sym::round_ties_even_f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::nearbyintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::nearbyintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::nearbyintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::nearbyintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::roundevenf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16),
sym::roundevenf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32),
sym::roundevenf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64),
sym::roundevenf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128),
sym::volatile_load | sym::unaligned_volatile_load => { sym::volatile_load | sym::unaligned_volatile_load => {
(1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)) (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))
} }

View file

@ -1337,10 +1337,6 @@ symbols! {
native_link_modifiers_whole_archive, native_link_modifiers_whole_archive,
natvis_file, natvis_file,
ne, ne,
nearbyintf128,
nearbyintf16,
nearbyintf32,
nearbyintf64,
needs_allocator, needs_allocator,
needs_drop, needs_drop,
needs_panic_runtime, needs_panic_runtime,
@ -1655,20 +1651,16 @@ symbols! {
return_position_impl_trait_in_trait, return_position_impl_trait_in_trait,
return_type_notation, return_type_notation,
rhs, rhs,
rintf128,
rintf16,
rintf32,
rintf64,
riscv_target_feature, riscv_target_feature,
rlib, rlib,
ropi, ropi,
ropi_rwpi: "ropi-rwpi", ropi_rwpi: "ropi-rwpi",
rotate_left, rotate_left,
rotate_right, rotate_right,
roundevenf128, round_ties_even_f128,
roundevenf16, round_ties_even_f16,
roundevenf32, round_ties_even_f32,
roundevenf64, round_ties_even_f64,
roundf128, roundf128,
roundf16, roundf16,
roundf32, roundf32,

View file

@ -2739,110 +2739,112 @@ pub unsafe fn truncf128(_x: f128) -> f128 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even
/// so this rounds half-way cases to the number with an even least significant digit. /// least significant digit.
///
/// May raise an inexact floating-point exception if the argument is not an integer.
/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
/// cannot actually be utilized from Rust code.
/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`.
/// ///
/// The stabilized version of this intrinsic is /// The stabilized version of this intrinsic is
/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind] #[rustc_nounwind]
pub unsafe fn rintf16(_x: f16) -> f16 { #[cfg(not(bootstrap))]
pub unsafe fn round_ties_even_f16(_x: f16) -> f16 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit. /// To be removed on next bootstrap bump.
/// #[cfg(bootstrap)]
/// May raise an inexact floating-point exception if the argument is not an integer. pub unsafe fn round_ties_even_f16(x: f16) -> f16 {
/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions #[rustc_intrinsic]
/// cannot actually be utilized from Rust code. #[rustc_intrinsic_must_be_overridden]
/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. #[rustc_nounwind]
unsafe fn rintf16(_x: f16) -> f16 {
unreachable!()
}
// SAFETY: this intrinsic isn't actually unsafe
unsafe { rintf16(x) }
}
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even
/// least significant digit.
/// ///
/// The stabilized version of this intrinsic is /// The stabilized version of this intrinsic is
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind] #[rustc_nounwind]
pub unsafe fn rintf32(_x: f32) -> f32 { #[cfg(not(bootstrap))]
pub unsafe fn round_ties_even_f32(_x: f32) -> f32 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit. /// To be removed on next bootstrap bump.
/// #[cfg(bootstrap)]
/// May raise an inexact floating-point exception if the argument is not an integer. pub unsafe fn round_ties_even_f32(x: f32) -> f32 {
/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions #[rustc_intrinsic]
/// cannot actually be utilized from Rust code. #[rustc_intrinsic_must_be_overridden]
/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. #[rustc_nounwind]
unsafe fn rintf32(_x: f32) -> f32 {
unreachable!()
}
// SAFETY: this intrinsic isn't actually unsafe
unsafe { rintf32(x) }
}
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number with an even
/// least significant digit.
/// ///
/// The stabilized version of this intrinsic is /// The stabilized version of this intrinsic is
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind] #[rustc_nounwind]
pub unsafe fn rintf64(_x: f64) -> f64 { #[cfg(not(bootstrap))]
pub unsafe fn round_ties_even_f64(_x: f64) -> f64 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit. /// To be removed on next bootstrap bump.
/// #[cfg(bootstrap)]
/// May raise an inexact floating-point exception if the argument is not an integer. pub unsafe fn round_ties_even_f64(x: f64) -> f64 {
/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions #[rustc_intrinsic]
/// cannot actually be utilized from Rust code. #[rustc_intrinsic_must_be_overridden]
/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. #[rustc_nounwind]
unsafe fn rintf64(_x: f64) -> f64 {
unreachable!()
}
// SAFETY: this intrinsic isn't actually unsafe
unsafe { rintf64(x) }
}
/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number with an even
/// least significant digit.
/// ///
/// The stabilized version of this intrinsic is /// The stabilized version of this intrinsic is
/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind] #[rustc_nounwind]
pub unsafe fn rintf128(_x: f128) -> f128 { #[cfg(not(bootstrap))]
pub unsafe fn round_ties_even_f128(_x: f128) -> f128 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, /// To be removed on next bootstrap bump.
/// so this rounds half-way cases to the number with an even least significant digit. #[cfg(bootstrap)]
/// pub unsafe fn round_ties_even_f128(x: f128) -> f128 {
/// This intrinsic does not have a stable counterpart. #[rustc_intrinsic]
#[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden]
#[rustc_intrinsic_must_be_overridden] #[rustc_nounwind]
#[rustc_nounwind] unsafe fn rintf128(_x: f128) -> f128 {
pub unsafe fn nearbyintf16(_x: f16) -> f16 { unreachable!()
unreachable!() }
}
/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, // SAFETY: this intrinsic isn't actually unsafe
/// so this rounds half-way cases to the number with an even least significant digit. unsafe { rintf128(x) }
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn nearbyintf32(_x: f32) -> f32 {
unreachable!()
}
/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn nearbyintf64(_x: f64) -> f64 {
unreachable!()
}
/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn nearbyintf128(_x: f128) -> f128 {
unreachable!()
} }
/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
@ -2886,47 +2888,6 @@ pub unsafe fn roundf128(_x: f128) -> f128 {
unreachable!() unreachable!()
} }
/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn roundevenf16(_x: f16) -> f16 {
unreachable!()
}
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn roundevenf32(_x: f32) -> f32 {
unreachable!()
}
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn roundevenf64(_x: f64) -> f64 {
unreachable!()
}
/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
pub unsafe fn roundevenf128(_x: f128) -> f128 {
unreachable!()
}
/// Float addition that allows optimizations based on algebraic rules. /// Float addition that allows optimizations based on algebraic rules.
/// May assume inputs are finite. /// May assume inputs are finite.
/// ///

View file

@ -129,7 +129,7 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")] #[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
pub fn round_ties_even(self) -> f128 { pub fn round_ties_even(self) -> f128 {
unsafe { intrinsics::rintf128(self) } unsafe { intrinsics::round_ties_even_f128(self) }
} }
/// Returns the integer part of `self`. /// Returns the integer part of `self`.

View file

@ -129,7 +129,7 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")] #[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
pub fn round_ties_even(self) -> f16 { pub fn round_ties_even(self) -> f16 {
unsafe { intrinsics::rintf16(self) } unsafe { intrinsics::round_ties_even_f16(self) }
} }
/// Returns the integer part of `self`. /// Returns the integer part of `self`.

View file

@ -125,7 +125,7 @@ impl f32 {
#[stable(feature = "round_ties_even", since = "1.77.0")] #[stable(feature = "round_ties_even", since = "1.77.0")]
#[inline] #[inline]
pub fn round_ties_even(self) -> f32 { pub fn round_ties_even(self) -> f32 {
unsafe { intrinsics::rintf32(self) } unsafe { intrinsics::round_ties_even_f32(self) }
} }
/// Returns the integer part of `self`. /// Returns the integer part of `self`.

View file

@ -125,7 +125,7 @@ impl f64 {
#[stable(feature = "round_ties_even", since = "1.77.0")] #[stable(feature = "round_ties_even", since = "1.77.0")]
#[inline] #[inline]
pub fn round_ties_even(self) -> f64 { pub fn round_ties_even(self) -> f64 {
unsafe { intrinsics::rintf64(self) } unsafe { intrinsics::round_ties_even_f64(self) }
} }
/// Returns the integer part of `self`. /// Returns the integer part of `self`.

View file

@ -145,7 +145,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(Scalar::from_bool(branch), dest)?; this.write_scalar(Scalar::from_bool(branch), dest)?;
} }
"floorf16" | "ceilf16" | "truncf16" | "roundf16" | "rintf16" => { "floorf16" | "ceilf16" | "truncf16" | "roundf16" | "round_ties_even_f16" => {
let [f] = check_arg_count(args)?; let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f16()?; let f = this.read_scalar(f)?.to_f16()?;
let mode = match intrinsic_name { let mode = match intrinsic_name {
@ -153,14 +153,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"ceilf16" => Round::TowardPositive, "ceilf16" => Round::TowardPositive,
"truncf16" => Round::TowardZero, "truncf16" => Round::TowardZero,
"roundf16" => Round::NearestTiesToAway, "roundf16" => Round::NearestTiesToAway,
"rintf16" => Round::NearestTiesToEven, "round_ties_even_f16" => Round::NearestTiesToEven,
_ => bug!(), _ => bug!(),
}; };
let res = f.round_to_integral(mode).value; let res = f.round_to_integral(mode).value;
let res = this.adjust_nan(res, &[f]); let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => { "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "round_ties_even_f32" => {
let [f] = check_arg_count(args)?; let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f32()?; let f = this.read_scalar(f)?.to_f32()?;
let mode = match intrinsic_name { let mode = match intrinsic_name {
@ -168,14 +168,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"ceilf32" => Round::TowardPositive, "ceilf32" => Round::TowardPositive,
"truncf32" => Round::TowardZero, "truncf32" => Round::TowardZero,
"roundf32" => Round::NearestTiesToAway, "roundf32" => Round::NearestTiesToAway,
"rintf32" => Round::NearestTiesToEven, "round_ties_even_f32" => Round::NearestTiesToEven,
_ => bug!(), _ => bug!(),
}; };
let res = f.round_to_integral(mode).value; let res = f.round_to_integral(mode).value;
let res = this.adjust_nan(res, &[f]); let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => { "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "round_ties_even_f64" => {
let [f] = check_arg_count(args)?; let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f64()?; let f = this.read_scalar(f)?.to_f64()?;
let mode = match intrinsic_name { let mode = match intrinsic_name {
@ -183,14 +183,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"ceilf64" => Round::TowardPositive, "ceilf64" => Round::TowardPositive,
"truncf64" => Round::TowardZero, "truncf64" => Round::TowardZero,
"roundf64" => Round::NearestTiesToAway, "roundf64" => Round::NearestTiesToAway,
"rintf64" => Round::NearestTiesToEven, "round_ties_even_f64" => Round::NearestTiesToEven,
_ => bug!(), _ => bug!(),
}; };
let res = f.round_to_integral(mode).value; let res = f.round_to_integral(mode).value;
let res = this.adjust_nan(res, &[f]); let res = this.adjust_nan(res, &[f]);
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"floorf128" | "ceilf128" | "truncf128" | "roundf128" | "rintf128" => { "floorf128" | "ceilf128" | "truncf128" | "roundf128" | "round_ties_even_f128" => {
let [f] = check_arg_count(args)?; let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f128()?; let f = this.read_scalar(f)?.to_f128()?;
let mode = match intrinsic_name { let mode = match intrinsic_name {
@ -198,7 +198,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"ceilf128" => Round::TowardPositive, "ceilf128" => Round::TowardPositive,
"truncf128" => Round::TowardZero, "truncf128" => Round::TowardZero,
"roundf128" => Round::NearestTiesToAway, "roundf128" => Round::NearestTiesToAway,
"rintf128" => Round::NearestTiesToEven, "round_ties_even_f128" => Round::NearestTiesToEven,
_ => bug!(), _ => bug!(),
}; };
let res = f.round_to_integral(mode).value; let res = f.round_to_integral(mode).value;

View file

@ -1,18 +0,0 @@
#![crate_type = "lib"]
#![feature(core_intrinsics)]
use std::intrinsics;
// CHECK-LABEL: @nearbyintf32
#[no_mangle]
pub unsafe fn nearbyintf32(a: f32) -> f32 {
// CHECK: llvm.nearbyint.f32
intrinsics::nearbyintf32(a)
}
// CHECK-LABEL: @nearbyintf64
#[no_mangle]
pub unsafe fn nearbyintf64(a: f64) -> f64 {
// CHECK: llvm.nearbyint.f64
intrinsics::nearbyintf64(a)
}

View file

@ -1,11 +0,0 @@
//@ run-pass
#![feature(core_intrinsics)]
use std::intrinsics::*;
fn main() {
unsafe {
assert_eq!(nearbyintf32(5.234f32), 5f32);
assert_eq!(nearbyintf64(6.777f64), 7f64);
}
}