Skip to content

Commit 62ea2b9

Browse files
Rollup merge of rust-lang#130568 - eduardosm:const-float-methods, r=RalfJung,tgross35
Make some float methods unstable `const fn` Some float methods are now `const fn` under the `const_float_methods` feature gate. I also made some unstable methods `const fn`, keeping their constness under their respective feature gate. In order to support `min`, `max`, `abs` and `copysign`, the implementation of some intrinsics had to be moved from Miri to rustc_const_eval (cc ```@RalfJung).``` Tracking issue: rust-lang#130843 ```rust impl <float> { // #[feature(const_float_methods)] pub const fn recip(self) -> Self; pub const fn to_degrees(self) -> Self; pub const fn to_radians(self) -> Self; pub const fn max(self, other: Self) -> Self; pub const fn min(self, other: Self) -> Self; pub const fn clamp(self, min: Self, max: Self) -> Self; pub const fn abs(self) -> Self; pub const fn signum(self) -> Self; pub const fn copysign(self, sign: Self) -> Self; // #[feature(float_minimum_maximum)] pub const fn maximum(self, other: Self) -> Self; pub const fn minimum(self, other: Self) -> Self; // Only f16/f128 (f32/f64 already const) pub const fn is_sign_positive(self) -> bool; pub const fn is_sign_negative(self) -> bool; pub const fn next_up(self) -> Self; pub const fn next_down(self) -> Self; } ``` r? libs-api
2 parents 1a39c53 + 029a881 commit 62ea2b9

File tree

18 files changed

+515
-266
lines changed

18 files changed

+515
-266
lines changed

Diff for: compiler/rustc_const_eval/src/interpret/cast.rs

+10-17
Original file line numberDiff line numberDiff line change
@@ -334,19 +334,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
334334
{
335335
use rustc_type_ir::TyKind::*;
336336

337-
fn adjust_nan<
338-
'tcx,
339-
M: Machine<'tcx>,
340-
F1: rustc_apfloat::Float + FloatConvert<F2>,
341-
F2: rustc_apfloat::Float,
342-
>(
343-
ecx: &InterpCx<'tcx, M>,
344-
f1: F1,
345-
f2: F2,
346-
) -> F2 {
347-
if f2.is_nan() { M::generate_nan(ecx, &[f1]) } else { f2 }
348-
}
349-
350337
match *dest_ty.kind() {
351338
// float -> uint
352339
Uint(t) => {
@@ -367,11 +354,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
367354
}
368355
// float -> float
369356
Float(fty) => match fty {
370-
FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)),
371-
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
372-
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
357+
FloatTy::F16 => {
358+
Scalar::from_f16(self.adjust_nan(f.convert(&mut false).value, &[f]))
359+
}
360+
FloatTy::F32 => {
361+
Scalar::from_f32(self.adjust_nan(f.convert(&mut false).value, &[f]))
362+
}
363+
FloatTy::F64 => {
364+
Scalar::from_f64(self.adjust_nan(f.convert(&mut false).value, &[f]))
365+
}
373366
FloatTy::F128 => {
374-
Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value))
367+
Scalar::from_f128(self.adjust_nan(f.convert(&mut false).value, &[f]))
375368
}
376369
},
377370
// That's it.

Diff for: compiler/rustc_const_eval/src/interpret/eval_context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
599599
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
600600
Frame::generate_stacktrace_from_stack(self.stack())
601601
}
602+
603+
pub fn adjust_nan<F1, F2>(&self, f: F2, inputs: &[F1]) -> F2
604+
where
605+
F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>,
606+
F2: rustc_apfloat::Float,
607+
{
608+
if f.is_nan() { M::generate_nan(self, inputs) } else { f }
609+
}
602610
}
603611

604612
#[doc(hidden)]

Diff for: compiler/rustc_const_eval/src/interpret/intrinsics.rs

+80
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
use std::assert_matches::assert_matches;
66

7+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
78
use rustc_hir::def_id::DefId;
89
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
910
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
@@ -438,6 +439,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
438439
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
439440
}
440441

442+
sym::minnumf16 => self.float_min_intrinsic::<Half>(args, dest)?,
443+
sym::minnumf32 => self.float_min_intrinsic::<Single>(args, dest)?,
444+
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
445+
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
446+
447+
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
448+
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
449+
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
450+
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
451+
452+
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
453+
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
454+
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
455+
sym::copysignf128 => self.float_copysign_intrinsic::<Quad>(args, dest)?,
456+
457+
sym::fabsf16 => self.float_abs_intrinsic::<Half>(args, dest)?,
458+
sym::fabsf32 => self.float_abs_intrinsic::<Single>(args, dest)?,
459+
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
460+
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
461+
441462
// Unsupported intrinsic: skip the return_to_block below.
442463
_ => return interp_ok(false),
443464
}
@@ -697,4 +718,63 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
697718
let rhs_bytes = get_bytes(self, rhs)?;
698719
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
699720
}
721+
722+
fn float_min_intrinsic<F>(
723+
&mut self,
724+
args: &[OpTy<'tcx, M::Provenance>],
725+
dest: &MPlaceTy<'tcx, M::Provenance>,
726+
) -> InterpResult<'tcx, ()>
727+
where
728+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
729+
{
730+
let a: F = self.read_scalar(&args[0])?.to_float()?;
731+
let b: F = self.read_scalar(&args[1])?.to_float()?;
732+
let res = self.adjust_nan(a.min(b), &[a, b]);
733+
self.write_scalar(res, dest)?;
734+
interp_ok(())
735+
}
736+
737+
fn float_max_intrinsic<F>(
738+
&mut self,
739+
args: &[OpTy<'tcx, M::Provenance>],
740+
dest: &MPlaceTy<'tcx, M::Provenance>,
741+
) -> InterpResult<'tcx, ()>
742+
where
743+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
744+
{
745+
let a: F = self.read_scalar(&args[0])?.to_float()?;
746+
let b: F = self.read_scalar(&args[1])?.to_float()?;
747+
let res = self.adjust_nan(a.max(b), &[a, b]);
748+
self.write_scalar(res, dest)?;
749+
interp_ok(())
750+
}
751+
752+
fn float_copysign_intrinsic<F>(
753+
&mut self,
754+
args: &[OpTy<'tcx, M::Provenance>],
755+
dest: &MPlaceTy<'tcx, M::Provenance>,
756+
) -> InterpResult<'tcx, ()>
757+
where
758+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
759+
{
760+
let a: F = self.read_scalar(&args[0])?.to_float()?;
761+
let b: F = self.read_scalar(&args[1])?.to_float()?;
762+
// bitwise, no NaN adjustments
763+
self.write_scalar(a.copy_sign(b), dest)?;
764+
interp_ok(())
765+
}
766+
767+
fn float_abs_intrinsic<F>(
768+
&mut self,
769+
args: &[OpTy<'tcx, M::Provenance>],
770+
dest: &MPlaceTy<'tcx, M::Provenance>,
771+
) -> InterpResult<'tcx, ()>
772+
where
773+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
774+
{
775+
let x: F = self.read_scalar(&args[0])?.to_float()?;
776+
// bitwise, no NaN adjustments
777+
self.write_scalar(x.abs(), dest)?;
778+
interp_ok(())
779+
}
700780
}

Diff for: compiler/rustc_const_eval/src/interpret/operator.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
6464
use rustc_middle::mir::BinOp::*;
6565

6666
// Performs appropriate non-deterministic adjustments of NaN results.
67-
let adjust_nan =
68-
|f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } };
67+
let adjust_nan = |f: F| -> F { self.adjust_nan(f, &[l, r]) };
6968

7069
match bin_op {
7170
Eq => ImmTy::from_bool(l == r, *self.tcx),

0 commit comments

Comments
 (0)