Skip to content

Make algebraic functions into const fn items. #140172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,31 @@ 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: Miri should add some non-determinism 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
Expand Down
10 changes: 5 additions & 5 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
///
Expand Down
15 changes: 10 additions & 5 deletions library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}
}
15 changes: 10 additions & 5 deletions library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}
}
15 changes: 10 additions & 5 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}
}
15 changes: 10 additions & 5 deletions library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}
}
26 changes: 0 additions & 26 deletions src/tools/miri/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading