Make algebraic intrinsics into 'const fn' items; Make algebraic functions of 'f16', 'f32', 'f64', and 'f128' into 'const fn' items;

This commit is contained in:
Gabriel Bjørnager Jensen 2025-04-22 16:39:32 +02:00
parent 6bc57c6bf7
commit 82ccba1fd7
7 changed files with 71 additions and 51 deletions

View file

@ -158,6 +158,32 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.copy_op(&val, dest)?;
}
sym::fadd_algebraic
| sym::fsub_algebraic
| sym::fmul_algebraic
| sym::fdiv_algebraic
| sym::frem_algebraic => {
let a = self.read_immediate(&args[0])?;
let b = self.read_immediate(&args[1])?;
let op = match intrinsic_name {
sym::fadd_algebraic => BinOp::Add,
sym::fsub_algebraic => BinOp::Sub,
sym::fmul_algebraic => BinOp::Mul,
sym::fdiv_algebraic => BinOp::Div,
sym::frem_algebraic => BinOp::Rem,
_ => bug!(),
};
let res = self.binary_op(op, &a, &b)?;
// `binary_op` already called `generate_nan` if needed.
// FIXME: Tests do likely benefit from us adding some randomness to the result here to catch any dependences on exact computations. This has previously been done, but the behaviour was removed as part of constification.
self.write_immediate(*res, dest)?;
}
sym::ctpop
| sym::cttz
| sym::cttz_nonzero

View file

@ -2429,35 +2429,35 @@ pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> In
/// Stabilized as [`f16::algebraic_add`], [`f32::algebraic_add`], [`f64::algebraic_add`] and [`f128::algebraic_add`].
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
pub const fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float subtraction that allows optimizations based on algebraic rules.
///
/// Stabilized as [`f16::algebraic_sub`], [`f32::algebraic_sub`], [`f64::algebraic_sub`] and [`f128::algebraic_sub`].
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
pub const fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float multiplication that allows optimizations based on algebraic rules.
///
/// Stabilized as [`f16::algebraic_mul`], [`f32::algebraic_mul`], [`f64::algebraic_mul`] and [`f128::algebraic_mul`].
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
pub const fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float division that allows optimizations based on algebraic rules.
///
/// Stabilized as [`f16::algebraic_div`], [`f32::algebraic_div`], [`f64::algebraic_div`] and [`f128::algebraic_div`].
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
pub const fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
/// Float remainder that allows optimizations based on algebraic rules.
///
/// Stabilized as [`f16::algebraic_rem`], [`f32::algebraic_rem`], [`f64::algebraic_rem`] and [`f128::algebraic_rem`].
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
pub const fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
/// Returns the number of bits set in an integer type `T`
///

View file

@ -1370,8 +1370,9 @@ impl f128 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_add(self, rhs: f128) -> f128 {
pub const fn algebraic_add(self, rhs: f128) -> f128 {
intrinsics::fadd_algebraic(self, rhs)
}
@ -1380,8 +1381,9 @@ impl f128 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_sub(self, rhs: f128) -> f128 {
pub const fn algebraic_sub(self, rhs: f128) -> f128 {
intrinsics::fsub_algebraic(self, rhs)
}
@ -1390,8 +1392,9 @@ impl f128 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_mul(self, rhs: f128) -> f128 {
pub const fn algebraic_mul(self, rhs: f128) -> f128 {
intrinsics::fmul_algebraic(self, rhs)
}
@ -1400,8 +1403,9 @@ impl f128 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_div(self, rhs: f128) -> f128 {
pub const fn algebraic_div(self, rhs: f128) -> f128 {
intrinsics::fdiv_algebraic(self, rhs)
}
@ -1410,8 +1414,9 @@ impl f128 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_rem(self, rhs: f128) -> f128 {
pub const fn algebraic_rem(self, rhs: f128) -> f128 {
intrinsics::frem_algebraic(self, rhs)
}
}

View file

@ -1346,8 +1346,9 @@ impl f16 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_add(self, rhs: f16) -> f16 {
pub const fn algebraic_add(self, rhs: f16) -> f16 {
intrinsics::fadd_algebraic(self, rhs)
}
@ -1356,8 +1357,9 @@ impl f16 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_sub(self, rhs: f16) -> f16 {
pub const fn algebraic_sub(self, rhs: f16) -> f16 {
intrinsics::fsub_algebraic(self, rhs)
}
@ -1366,8 +1368,9 @@ impl f16 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_mul(self, rhs: f16) -> f16 {
pub const fn algebraic_mul(self, rhs: f16) -> f16 {
intrinsics::fmul_algebraic(self, rhs)
}
@ -1376,8 +1379,9 @@ impl f16 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_div(self, rhs: f16) -> f16 {
pub const fn algebraic_div(self, rhs: f16) -> f16 {
intrinsics::fdiv_algebraic(self, rhs)
}
@ -1386,8 +1390,9 @@ impl f16 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_rem(self, rhs: f16) -> f16 {
pub const fn algebraic_rem(self, rhs: f16) -> f16 {
intrinsics::frem_algebraic(self, rhs)
}
}

View file

@ -1512,8 +1512,9 @@ impl f32 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_add(self, rhs: f32) -> f32 {
pub const fn algebraic_add(self, rhs: f32) -> f32 {
intrinsics::fadd_algebraic(self, rhs)
}
@ -1522,8 +1523,9 @@ impl f32 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_sub(self, rhs: f32) -> f32 {
pub const fn algebraic_sub(self, rhs: f32) -> f32 {
intrinsics::fsub_algebraic(self, rhs)
}
@ -1532,8 +1534,9 @@ impl f32 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_mul(self, rhs: f32) -> f32 {
pub const fn algebraic_mul(self, rhs: f32) -> f32 {
intrinsics::fmul_algebraic(self, rhs)
}
@ -1542,8 +1545,9 @@ impl f32 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_div(self, rhs: f32) -> f32 {
pub const fn algebraic_div(self, rhs: f32) -> f32 {
intrinsics::fdiv_algebraic(self, rhs)
}
@ -1552,8 +1556,9 @@ impl f32 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_rem(self, rhs: f32) -> f32 {
pub const fn algebraic_rem(self, rhs: f32) -> f32 {
intrinsics::frem_algebraic(self, rhs)
}
}

View file

@ -1511,8 +1511,9 @@ impl f64 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_add(self, rhs: f64) -> f64 {
pub const fn algebraic_add(self, rhs: f64) -> f64 {
intrinsics::fadd_algebraic(self, rhs)
}
@ -1521,8 +1522,9 @@ impl f64 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_sub(self, rhs: f64) -> f64 {
pub const fn algebraic_sub(self, rhs: f64) -> f64 {
intrinsics::fsub_algebraic(self, rhs)
}
@ -1531,8 +1533,9 @@ impl f64 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_mul(self, rhs: f64) -> f64 {
pub const fn algebraic_mul(self, rhs: f64) -> f64 {
intrinsics::fmul_algebraic(self, rhs)
}
@ -1541,8 +1544,9 @@ impl f64 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_div(self, rhs: f64) -> f64 {
pub const fn algebraic_div(self, rhs: f64) -> f64 {
intrinsics::fdiv_algebraic(self, rhs)
}
@ -1551,8 +1555,9 @@ impl f64 {
/// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_algebraic", issue = "136469")]
#[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
#[inline]
pub fn algebraic_rem(self, rhs: f64) -> f64 {
pub const fn algebraic_rem(self, rhs: f64) -> f64 {
intrinsics::frem_algebraic(self, rhs)
}
}

View file

@ -391,32 +391,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(res, dest)?;
}
#[rustfmt::skip]
| "fadd_algebraic"
| "fsub_algebraic"
| "fmul_algebraic"
| "fdiv_algebraic"
| "frem_algebraic"
=> {
let [a, b] = check_intrinsic_arg_count(args)?;
let a = this.read_immediate(a)?;
let b = this.read_immediate(b)?;
let op = match intrinsic_name {
"fadd_algebraic" => mir::BinOp::Add,
"fsub_algebraic" => mir::BinOp::Sub,
"fmul_algebraic" => mir::BinOp::Mul,
"fdiv_algebraic" => mir::BinOp::Div,
"frem_algebraic" => mir::BinOp::Rem,
_ => bug!(),
};
let res = this.binary_op(op, &a, &b)?;
// `binary_op` already called `generate_nan` if needed.
// Apply a relative error of 4ULP to simulate non-deterministic precision loss
// due to optimizations.
let res = apply_random_float_error_to_imm(this, res, 2 /* log2(4) */)?;
this.write_immediate(*res, dest)?;
}
#[rustfmt::skip]
| "fadd_fast"
| "fsub_fast"