Skip to content

Commit a1d9cc4

Browse files
committed
Add const support for float rounding methods
Add const support for the float rounding methods floor, ceil, trunc, fract, round and round_ties_even. This works by moving the calculation logic from src/tools/miri/src/intrinsics/mod.rs into compiler/rustc_const_eval/src/interpret/intrinsics.rs. All relevant method definitions were adjusted to include the `const` keyword for all supported float types: f16, f32, f64 and f128. The constness is hidden behind the feature gate feature(const_float_round_methods) which is tracked in #141555 This commit is a squash of the following commits: - test: add tests that we expect to pass when float rounding becomes const - feat: make float rounding methods `const` - fix: replace `rustc_allow_const_fn_unstable(core_intrinsics)` attribute with `#[rustc_const_unstable(feature = "f128", issue = "116909")]` in `library/core/src/num/f128.rs` - revert: undo update to `library/stdarch` - refactor: replace multiple `float_<mode>_intrinsic` rounding methods with a single, parametrized one - fix: add `#[cfg(not(bootstrap))]` to new const method tests - test: add extra sign tests to check `+0.0` and `-0.0` - revert: undo accidental changes to `round` docs - fix: gate `const` float round method behind `const_float_round_methods` - fix: remove unnecessary `#![feature(const_float_methods)]` - fix: remove unnecessary `#![feature(const_float_methods)]` [2] - revert: undo changes to `tests/ui/consts/const-eval/float_methods.rs` - fix: adjust after rebase - test: fix float tests - test: add tests for `fract` - chore: add commented-out `const_float_round_methods` feature gates to `f16` and `f128` - fix: adjust NaN when rounding floats - chore: add FIXME comment for de-duplicating float tests - test: remove unnecessary test file `tests/ui/consts/const-eval/float_methods.rs` - test: fix tests after upstream simplification of how float tests are run
1 parent 8afd710 commit a1d9cc4

File tree

12 files changed

+333
-117
lines changed

12 files changed

+333
-117
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,103 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
518518
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
519519
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
520520

521+
sym::floorf16 => self.float_round_intrinsic::<Half>(
522+
args,
523+
dest,
524+
rustc_apfloat::Round::TowardNegative,
525+
)?,
526+
sym::floorf32 => self.float_round_intrinsic::<Single>(
527+
args,
528+
dest,
529+
rustc_apfloat::Round::TowardNegative,
530+
)?,
531+
sym::floorf64 => self.float_round_intrinsic::<Double>(
532+
args,
533+
dest,
534+
rustc_apfloat::Round::TowardNegative,
535+
)?,
536+
sym::floorf128 => self.float_round_intrinsic::<Quad>(
537+
args,
538+
dest,
539+
rustc_apfloat::Round::TowardNegative,
540+
)?,
541+
542+
sym::ceilf16 => self.float_round_intrinsic::<Half>(
543+
args,
544+
dest,
545+
rustc_apfloat::Round::TowardPositive,
546+
)?,
547+
sym::ceilf32 => self.float_round_intrinsic::<Single>(
548+
args,
549+
dest,
550+
rustc_apfloat::Round::TowardPositive,
551+
)?,
552+
sym::ceilf64 => self.float_round_intrinsic::<Double>(
553+
args,
554+
dest,
555+
rustc_apfloat::Round::TowardPositive,
556+
)?,
557+
sym::ceilf128 => self.float_round_intrinsic::<Quad>(
558+
args,
559+
dest,
560+
rustc_apfloat::Round::TowardPositive,
561+
)?,
562+
563+
sym::truncf16 => {
564+
self.float_round_intrinsic::<Half>(args, dest, rustc_apfloat::Round::TowardZero)?
565+
}
566+
sym::truncf32 => {
567+
self.float_round_intrinsic::<Single>(args, dest, rustc_apfloat::Round::TowardZero)?
568+
}
569+
sym::truncf64 => {
570+
self.float_round_intrinsic::<Double>(args, dest, rustc_apfloat::Round::TowardZero)?
571+
}
572+
sym::truncf128 => {
573+
self.float_round_intrinsic::<Quad>(args, dest, rustc_apfloat::Round::TowardZero)?
574+
}
575+
576+
sym::roundf16 => self.float_round_intrinsic::<Half>(
577+
args,
578+
dest,
579+
rustc_apfloat::Round::NearestTiesToAway,
580+
)?,
581+
sym::roundf32 => self.float_round_intrinsic::<Single>(
582+
args,
583+
dest,
584+
rustc_apfloat::Round::NearestTiesToAway,
585+
)?,
586+
sym::roundf64 => self.float_round_intrinsic::<Double>(
587+
args,
588+
dest,
589+
rustc_apfloat::Round::NearestTiesToAway,
590+
)?,
591+
sym::roundf128 => self.float_round_intrinsic::<Quad>(
592+
args,
593+
dest,
594+
rustc_apfloat::Round::NearestTiesToAway,
595+
)?,
596+
597+
sym::round_ties_even_f16 => self.float_round_intrinsic::<Half>(
598+
args,
599+
dest,
600+
rustc_apfloat::Round::NearestTiesToEven,
601+
)?,
602+
sym::round_ties_even_f32 => self.float_round_intrinsic::<Single>(
603+
args,
604+
dest,
605+
rustc_apfloat::Round::NearestTiesToEven,
606+
)?,
607+
sym::round_ties_even_f64 => self.float_round_intrinsic::<Double>(
608+
args,
609+
dest,
610+
rustc_apfloat::Round::NearestTiesToEven,
611+
)?,
612+
sym::round_ties_even_f128 => self.float_round_intrinsic::<Quad>(
613+
args,
614+
dest,
615+
rustc_apfloat::Round::NearestTiesToEven,
616+
)?,
617+
521618
// Unsupported intrinsic: skip the return_to_block below.
522619
_ => return interp_ok(false),
523620
}
@@ -900,4 +997,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
900997
self.write_scalar(x.abs(), dest)?;
901998
interp_ok(())
902999
}
1000+
1001+
fn float_round_intrinsic<F>(
1002+
&mut self,
1003+
args: &[OpTy<'tcx, M::Provenance>],
1004+
dest: &PlaceTy<'tcx, M::Provenance>,
1005+
mode: rustc_apfloat::Round,
1006+
) -> InterpResult<'tcx, ()>
1007+
where
1008+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
1009+
{
1010+
let x: F = self.read_scalar(&args[0])?.to_float()?;
1011+
let res = x.round_to_integral(mode).value;
1012+
let res = self.adjust_nan(res, &[x]);
1013+
self.write_scalar(res, dest)?;
1014+
interp_ok(())
1015+
}
9031016
}

library/core/src/intrinsics/mod.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,86 +2186,86 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
21862186
/// [`f16::floor`](../../std/primitive.f16.html#method.floor)
21872187
#[rustc_intrinsic]
21882188
#[rustc_nounwind]
2189-
pub unsafe fn floorf16(x: f16) -> f16;
2189+
pub const unsafe fn floorf16(x: f16) -> f16;
21902190
/// Returns the largest integer less than or equal to an `f32`.
21912191
///
21922192
/// The stabilized version of this intrinsic is
21932193
/// [`f32::floor`](../../std/primitive.f32.html#method.floor)
21942194
#[rustc_intrinsic]
21952195
#[rustc_nounwind]
2196-
pub unsafe fn floorf32(x: f32) -> f32;
2196+
pub const unsafe fn floorf32(x: f32) -> f32;
21972197
/// Returns the largest integer less than or equal to an `f64`.
21982198
///
21992199
/// The stabilized version of this intrinsic is
22002200
/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
22012201
#[rustc_intrinsic]
22022202
#[rustc_nounwind]
2203-
pub unsafe fn floorf64(x: f64) -> f64;
2203+
pub const unsafe fn floorf64(x: f64) -> f64;
22042204
/// Returns the largest integer less than or equal to an `f128`.
22052205
///
22062206
/// The stabilized version of this intrinsic is
22072207
/// [`f128::floor`](../../std/primitive.f128.html#method.floor)
22082208
#[rustc_intrinsic]
22092209
#[rustc_nounwind]
2210-
pub unsafe fn floorf128(x: f128) -> f128;
2210+
pub const unsafe fn floorf128(x: f128) -> f128;
22112211

22122212
/// Returns the smallest integer greater than or equal to an `f16`.
22132213
///
22142214
/// The stabilized version of this intrinsic is
22152215
/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
22162216
#[rustc_intrinsic]
22172217
#[rustc_nounwind]
2218-
pub unsafe fn ceilf16(x: f16) -> f16;
2218+
pub const unsafe fn ceilf16(x: f16) -> f16;
22192219
/// Returns the smallest integer greater than or equal to an `f32`.
22202220
///
22212221
/// The stabilized version of this intrinsic is
22222222
/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
22232223
#[rustc_intrinsic]
22242224
#[rustc_nounwind]
2225-
pub unsafe fn ceilf32(x: f32) -> f32;
2225+
pub const unsafe fn ceilf32(x: f32) -> f32;
22262226
/// Returns the smallest integer greater than or equal to an `f64`.
22272227
///
22282228
/// The stabilized version of this intrinsic is
22292229
/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
22302230
#[rustc_intrinsic]
22312231
#[rustc_nounwind]
2232-
pub unsafe fn ceilf64(x: f64) -> f64;
2232+
pub const unsafe fn ceilf64(x: f64) -> f64;
22332233
/// Returns the smallest integer greater than or equal to an `f128`.
22342234
///
22352235
/// The stabilized version of this intrinsic is
22362236
/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
22372237
#[rustc_intrinsic]
22382238
#[rustc_nounwind]
2239-
pub unsafe fn ceilf128(x: f128) -> f128;
2239+
pub const unsafe fn ceilf128(x: f128) -> f128;
22402240

22412241
/// Returns the integer part of an `f16`.
22422242
///
22432243
/// The stabilized version of this intrinsic is
22442244
/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
22452245
#[rustc_intrinsic]
22462246
#[rustc_nounwind]
2247-
pub unsafe fn truncf16(x: f16) -> f16;
2247+
pub const unsafe fn truncf16(x: f16) -> f16;
22482248
/// Returns the integer part of an `f32`.
22492249
///
22502250
/// The stabilized version of this intrinsic is
22512251
/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
22522252
#[rustc_intrinsic]
22532253
#[rustc_nounwind]
2254-
pub unsafe fn truncf32(x: f32) -> f32;
2254+
pub const unsafe fn truncf32(x: f32) -> f32;
22552255
/// Returns the integer part of an `f64`.
22562256
///
22572257
/// The stabilized version of this intrinsic is
22582258
/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
22592259
#[rustc_intrinsic]
22602260
#[rustc_nounwind]
2261-
pub unsafe fn truncf64(x: f64) -> f64;
2261+
pub const unsafe fn truncf64(x: f64) -> f64;
22622262
/// Returns the integer part of an `f128`.
22632263
///
22642264
/// The stabilized version of this intrinsic is
22652265
/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
22662266
#[rustc_intrinsic]
22672267
#[rustc_nounwind]
2268-
pub unsafe fn truncf128(x: f128) -> f128;
2268+
pub const unsafe fn truncf128(x: f128) -> f128;
22692269

22702270
/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even
22712271
/// least significant digit.
@@ -2274,7 +2274,7 @@ pub unsafe fn truncf128(x: f128) -> f128;
22742274
/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
22752275
#[rustc_intrinsic]
22762276
#[rustc_nounwind]
2277-
pub fn round_ties_even_f16(x: f16) -> f16;
2277+
pub const fn round_ties_even_f16(x: f16) -> f16;
22782278

22792279
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even
22802280
/// least significant digit.
@@ -2283,7 +2283,7 @@ pub fn round_ties_even_f16(x: f16) -> f16;
22832283
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
22842284
#[rustc_intrinsic]
22852285
#[rustc_nounwind]
2286-
pub fn round_ties_even_f32(x: f32) -> f32;
2286+
pub const fn round_ties_even_f32(x: f32) -> f32;
22872287

22882288
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number with an even
22892289
/// least significant digit.
@@ -2292,7 +2292,7 @@ pub fn round_ties_even_f32(x: f32) -> f32;
22922292
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
22932293
#[rustc_intrinsic]
22942294
#[rustc_nounwind]
2295-
pub fn round_ties_even_f64(x: f64) -> f64;
2295+
pub const fn round_ties_even_f64(x: f64) -> f64;
22962296

22972297
/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number with an even
22982298
/// least significant digit.
@@ -2301,36 +2301,36 @@ pub fn round_ties_even_f64(x: f64) -> f64;
23012301
/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
23022302
#[rustc_intrinsic]
23032303
#[rustc_nounwind]
2304-
pub fn round_ties_even_f128(x: f128) -> f128;
2304+
pub const fn round_ties_even_f128(x: f128) -> f128;
23052305

23062306
/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
23072307
///
23082308
/// The stabilized version of this intrinsic is
23092309
/// [`f16::round`](../../std/primitive.f16.html#method.round)
23102310
#[rustc_intrinsic]
23112311
#[rustc_nounwind]
2312-
pub unsafe fn roundf16(x: f16) -> f16;
2312+
pub const unsafe fn roundf16(x: f16) -> f16;
23132313
/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
23142314
///
23152315
/// The stabilized version of this intrinsic is
23162316
/// [`f32::round`](../../std/primitive.f32.html#method.round)
23172317
#[rustc_intrinsic]
23182318
#[rustc_nounwind]
2319-
pub unsafe fn roundf32(x: f32) -> f32;
2319+
pub const unsafe fn roundf32(x: f32) -> f32;
23202320
/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
23212321
///
23222322
/// The stabilized version of this intrinsic is
23232323
/// [`f64::round`](../../std/primitive.f64.html#method.round)
23242324
#[rustc_intrinsic]
23252325
#[rustc_nounwind]
2326-
pub unsafe fn roundf64(x: f64) -> f64;
2326+
pub const unsafe fn roundf64(x: f64) -> f64;
23272327
/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
23282328
///
23292329
/// The stabilized version of this intrinsic is
23302330
/// [`f128::round`](../../std/primitive.f128.html#method.round)
23312331
#[rustc_intrinsic]
23322332
#[rustc_nounwind]
2333-
pub unsafe fn roundf128(x: f128) -> f128;
2333+
pub const unsafe fn roundf128(x: f128) -> f128;
23342334

23352335
/// Float addition that allows optimizations based on algebraic rules.
23362336
/// May assume inputs are finite.

library/core/src/num/f128.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,8 +1447,10 @@ impl f128 {
14471447
#[inline]
14481448
#[rustc_allow_incoherent_impl]
14491449
#[unstable(feature = "f128", issue = "116909")]
1450+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1451+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
14501452
#[must_use = "method returns a new number and does not mutate the original value"]
1451-
pub fn floor(self) -> f128 {
1453+
pub const fn floor(self) -> f128 {
14521454
// SAFETY: intrinsic with no preconditions
14531455
unsafe { intrinsics::floorf128(self) }
14541456
}
@@ -1477,8 +1479,10 @@ impl f128 {
14771479
#[doc(alias = "ceiling")]
14781480
#[rustc_allow_incoherent_impl]
14791481
#[unstable(feature = "f128", issue = "116909")]
1482+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1483+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
14801484
#[must_use = "method returns a new number and does not mutate the original value"]
1481-
pub fn ceil(self) -> f128 {
1485+
pub const fn ceil(self) -> f128 {
14821486
// SAFETY: intrinsic with no preconditions
14831487
unsafe { intrinsics::ceilf128(self) }
14841488
}
@@ -1513,8 +1517,10 @@ impl f128 {
15131517
#[inline]
15141518
#[rustc_allow_incoherent_impl]
15151519
#[unstable(feature = "f128", issue = "116909")]
1520+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1521+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
15161522
#[must_use = "method returns a new number and does not mutate the original value"]
1517-
pub fn round(self) -> f128 {
1523+
pub const fn round(self) -> f128 {
15181524
// SAFETY: intrinsic with no preconditions
15191525
unsafe { intrinsics::roundf128(self) }
15201526
}
@@ -1547,8 +1553,10 @@ impl f128 {
15471553
#[inline]
15481554
#[rustc_allow_incoherent_impl]
15491555
#[unstable(feature = "f128", issue = "116909")]
1556+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1557+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
15501558
#[must_use = "method returns a new number and does not mutate the original value"]
1551-
pub fn round_ties_even(self) -> f128 {
1559+
pub const fn round_ties_even(self) -> f128 {
15521560
intrinsics::round_ties_even_f128(self)
15531561
}
15541562

@@ -1579,8 +1587,10 @@ impl f128 {
15791587
#[doc(alias = "truncate")]
15801588
#[rustc_allow_incoherent_impl]
15811589
#[unstable(feature = "f128", issue = "116909")]
1590+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1591+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
15821592
#[must_use = "method returns a new number and does not mutate the original value"]
1583-
pub fn trunc(self) -> f128 {
1593+
pub const fn trunc(self) -> f128 {
15841594
// SAFETY: intrinsic with no preconditions
15851595
unsafe { intrinsics::truncf128(self) }
15861596
}
@@ -1610,8 +1620,10 @@ impl f128 {
16101620
#[inline]
16111621
#[rustc_allow_incoherent_impl]
16121622
#[unstable(feature = "f128", issue = "116909")]
1623+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
1624+
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
16131625
#[must_use = "method returns a new number and does not mutate the original value"]
1614-
pub fn fract(self) -> f128 {
1626+
pub const fn fract(self) -> f128 {
16151627
self - self.trunc()
16161628
}
16171629

0 commit comments

Comments
 (0)