Skip to content

Commit 1f880d9

Browse files
committed
Auto merge of rust-lang#148446 - GuillaumeGomez:rollup-lxwlqol, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - rust-lang#135099 (Add FileCheck annotations to mir-opt/copy-prop) - rust-lang#145903 (Give correct suggestion for a typo in raw pointers) - rust-lang#147520 (Port the remaining SIMD intrinsics to const-eval) - rust-lang#148068 (rustdoc: Use configured target modifiers when collecting doctests) - rust-lang#148099 (Prepare to move debugger discovery from compiletest to bootstrap) - rust-lang#148268 (rustdoc: fix `--emit=dep-info` on scraped examples) - rust-lang#148306 (Remove double check when decoding ExpnId to avoid races) - rust-lang#148378 (Fix documentation for std::panic::update_hook) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f5711a5 + 871692a commit 1f880d9

File tree

50 files changed

+1335
-371
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1335
-371
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 124 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ use super::{
2525
};
2626
use crate::fluent_generated as fluent;
2727

28+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29+
enum MulAddType {
30+
/// Used with `fma` and `simd_fma`, always uses fused-multiply-add
31+
Fused,
32+
/// Used with `fmuladd` and `simd_relaxed_fma`, nondeterministically determines whether to use
33+
/// fma or simple multiply-add
34+
Nondeterministic,
35+
}
36+
37+
#[derive(Copy, Clone)]
38+
pub(crate) enum MinMax {
39+
/// The IEEE `Minimum` operation - see `f32::minimum` etc
40+
/// In particular, `-0.0` is considered smaller than `+0.0` and
41+
/// if either input is NaN, the result is NaN.
42+
Minimum,
43+
/// The IEEE `MinNum` operation - see `f32::min` etc
44+
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
45+
/// and is one argument is NaN, the other one is returned.
46+
MinNum,
47+
/// The IEEE `Maximum` operation - see `f32::maximum` etc
48+
/// In particular, `-0.0` is considered smaller than `+0.0` and
49+
/// if either input is NaN, the result is NaN.
50+
Maximum,
51+
/// The IEEE `MaxNum` operation - see `f32::max` etc
52+
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
53+
/// and is one argument is NaN, the other one is returned.
54+
MaxNum,
55+
}
56+
2857
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
2958
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (AllocId, u64) {
3059
let path = crate::util::type_name(tcx, ty);
@@ -504,25 +533,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
504533
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
505534
}
506535

507-
sym::minnumf16 => self.float_min_intrinsic::<Half>(args, dest)?,
508-
sym::minnumf32 => self.float_min_intrinsic::<Single>(args, dest)?,
509-
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
510-
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
536+
sym::minnumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::MinNum, dest)?,
537+
sym::minnumf32 => self.float_minmax_intrinsic::<Single>(args, MinMax::MinNum, dest)?,
538+
sym::minnumf64 => self.float_minmax_intrinsic::<Double>(args, MinMax::MinNum, dest)?,
539+
sym::minnumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::MinNum, dest)?,
511540

512-
sym::minimumf16 => self.float_minimum_intrinsic::<Half>(args, dest)?,
513-
sym::minimumf32 => self.float_minimum_intrinsic::<Single>(args, dest)?,
514-
sym::minimumf64 => self.float_minimum_intrinsic::<Double>(args, dest)?,
515-
sym::minimumf128 => self.float_minimum_intrinsic::<Quad>(args, dest)?,
541+
sym::minimumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::Minimum, dest)?,
542+
sym::minimumf32 => {
543+
self.float_minmax_intrinsic::<Single>(args, MinMax::Minimum, dest)?
544+
}
545+
sym::minimumf64 => {
546+
self.float_minmax_intrinsic::<Double>(args, MinMax::Minimum, dest)?
547+
}
548+
sym::minimumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::Minimum, dest)?,
516549

517-
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
518-
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
519-
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
520-
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
550+
sym::maxnumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::MaxNum, dest)?,
551+
sym::maxnumf32 => self.float_minmax_intrinsic::<Single>(args, MinMax::MaxNum, dest)?,
552+
sym::maxnumf64 => self.float_minmax_intrinsic::<Double>(args, MinMax::MaxNum, dest)?,
553+
sym::maxnumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::MaxNum, dest)?,
521554

522-
sym::maximumf16 => self.float_maximum_intrinsic::<Half>(args, dest)?,
523-
sym::maximumf32 => self.float_maximum_intrinsic::<Single>(args, dest)?,
524-
sym::maximumf64 => self.float_maximum_intrinsic::<Double>(args, dest)?,
525-
sym::maximumf128 => self.float_maximum_intrinsic::<Quad>(args, dest)?,
555+
sym::maximumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::Maximum, dest)?,
556+
sym::maximumf32 => {
557+
self.float_minmax_intrinsic::<Single>(args, MinMax::Maximum, dest)?
558+
}
559+
sym::maximumf64 => {
560+
self.float_minmax_intrinsic::<Double>(args, MinMax::Maximum, dest)?
561+
}
562+
sym::maximumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::Maximum, dest)?,
526563

527564
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
528565
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
@@ -630,14 +667,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
630667
dest,
631668
rustc_apfloat::Round::NearestTiesToEven,
632669
)?,
633-
sym::fmaf16 => self.fma_intrinsic::<Half>(args, dest)?,
634-
sym::fmaf32 => self.fma_intrinsic::<Single>(args, dest)?,
635-
sym::fmaf64 => self.fma_intrinsic::<Double>(args, dest)?,
636-
sym::fmaf128 => self.fma_intrinsic::<Quad>(args, dest)?,
637-
sym::fmuladdf16 => self.float_muladd_intrinsic::<Half>(args, dest)?,
638-
sym::fmuladdf32 => self.float_muladd_intrinsic::<Single>(args, dest)?,
639-
sym::fmuladdf64 => self.float_muladd_intrinsic::<Double>(args, dest)?,
640-
sym::fmuladdf128 => self.float_muladd_intrinsic::<Quad>(args, dest)?,
670+
sym::fmaf16 => self.float_muladd_intrinsic::<Half>(args, dest, MulAddType::Fused)?,
671+
sym::fmaf32 => self.float_muladd_intrinsic::<Single>(args, dest, MulAddType::Fused)?,
672+
sym::fmaf64 => self.float_muladd_intrinsic::<Double>(args, dest, MulAddType::Fused)?,
673+
sym::fmaf128 => self.float_muladd_intrinsic::<Quad>(args, dest, MulAddType::Fused)?,
674+
sym::fmuladdf16 => {
675+
self.float_muladd_intrinsic::<Half>(args, dest, MulAddType::Nondeterministic)?
676+
}
677+
sym::fmuladdf32 => {
678+
self.float_muladd_intrinsic::<Single>(args, dest, MulAddType::Nondeterministic)?
679+
}
680+
sym::fmuladdf64 => {
681+
self.float_muladd_intrinsic::<Double>(args, dest, MulAddType::Nondeterministic)?
682+
}
683+
sym::fmuladdf128 => {
684+
self.float_muladd_intrinsic::<Quad>(args, dest, MulAddType::Nondeterministic)?
685+
}
641686

642687
// Unsupported intrinsic: skip the return_to_block below.
643688
_ => return interp_ok(false),
@@ -919,76 +964,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
919964
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
920965
}
921966

922-
fn float_min_intrinsic<F>(
923-
&mut self,
924-
args: &[OpTy<'tcx, M::Provenance>],
925-
dest: &PlaceTy<'tcx, M::Provenance>,
926-
) -> InterpResult<'tcx, ()>
927-
where
928-
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
929-
{
930-
let a: F = self.read_scalar(&args[0])?.to_float()?;
931-
let b: F = self.read_scalar(&args[1])?.to_float()?;
932-
let res = if a == b {
933-
// They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
934-
// Let the machine decide which one to return.
935-
M::equal_float_min_max(self, a, b)
936-
} else {
937-
self.adjust_nan(a.min(b), &[a, b])
938-
};
939-
self.write_scalar(res, dest)?;
940-
interp_ok(())
941-
}
942-
943-
fn float_max_intrinsic<F>(
944-
&mut self,
945-
args: &[OpTy<'tcx, M::Provenance>],
946-
dest: &PlaceTy<'tcx, M::Provenance>,
947-
) -> InterpResult<'tcx, ()>
967+
fn float_minmax<F>(
968+
&self,
969+
a: Scalar<M::Provenance>,
970+
b: Scalar<M::Provenance>,
971+
op: MinMax,
972+
) -> InterpResult<'tcx, Scalar<M::Provenance>>
948973
where
949974
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
950975
{
951-
let a: F = self.read_scalar(&args[0])?.to_float()?;
952-
let b: F = self.read_scalar(&args[1])?.to_float()?;
953-
let res = if a == b {
976+
let a: F = a.to_float()?;
977+
let b: F = b.to_float()?;
978+
let res = if matches!(op, MinMax::MinNum | MinMax::MaxNum) && a == b {
954979
// They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
955980
// Let the machine decide which one to return.
956981
M::equal_float_min_max(self, a, b)
957982
} else {
958-
self.adjust_nan(a.max(b), &[a, b])
983+
let result = match op {
984+
MinMax::Minimum => a.minimum(b),
985+
MinMax::MinNum => a.min(b),
986+
MinMax::Maximum => a.maximum(b),
987+
MinMax::MaxNum => a.max(b),
988+
};
989+
self.adjust_nan(result, &[a, b])
959990
};
960-
self.write_scalar(res, dest)?;
961-
interp_ok(())
962-
}
963991

964-
fn float_minimum_intrinsic<F>(
965-
&mut self,
966-
args: &[OpTy<'tcx, M::Provenance>],
967-
dest: &PlaceTy<'tcx, M::Provenance>,
968-
) -> InterpResult<'tcx, ()>
969-
where
970-
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
971-
{
972-
let a: F = self.read_scalar(&args[0])?.to_float()?;
973-
let b: F = self.read_scalar(&args[1])?.to_float()?;
974-
let res = a.minimum(b);
975-
let res = self.adjust_nan(res, &[a, b]);
976-
self.write_scalar(res, dest)?;
977-
interp_ok(())
992+
interp_ok(res.into())
978993
}
979994

980-
fn float_maximum_intrinsic<F>(
995+
fn float_minmax_intrinsic<F>(
981996
&mut self,
982997
args: &[OpTy<'tcx, M::Provenance>],
998+
op: MinMax,
983999
dest: &PlaceTy<'tcx, M::Provenance>,
9841000
) -> InterpResult<'tcx, ()>
9851001
where
9861002
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
9871003
{
988-
let a: F = self.read_scalar(&args[0])?.to_float()?;
989-
let b: F = self.read_scalar(&args[1])?.to_float()?;
990-
let res = a.maximum(b);
991-
let res = self.adjust_nan(res, &[a, b]);
1004+
let res =
1005+
self.float_minmax::<F>(self.read_scalar(&args[0])?, self.read_scalar(&args[1])?, op)?;
9921006
self.write_scalar(res, dest)?;
9931007
interp_ok(())
9941008
}
@@ -1022,56 +1036,69 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10221036
interp_ok(())
10231037
}
10241038

1025-
fn float_round_intrinsic<F>(
1039+
fn float_round<F>(
10261040
&mut self,
1027-
args: &[OpTy<'tcx, M::Provenance>],
1028-
dest: &PlaceTy<'tcx, M::Provenance>,
1041+
x: Scalar<M::Provenance>,
10291042
mode: rustc_apfloat::Round,
1030-
) -> InterpResult<'tcx, ()>
1043+
) -> InterpResult<'tcx, Scalar<M::Provenance>>
10311044
where
10321045
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
10331046
{
1034-
let x: F = self.read_scalar(&args[0])?.to_float()?;
1047+
let x: F = x.to_float()?;
10351048
let res = x.round_to_integral(mode).value;
10361049
let res = self.adjust_nan(res, &[x]);
1037-
self.write_scalar(res, dest)?;
1038-
interp_ok(())
1050+
interp_ok(res.into())
10391051
}
10401052

1041-
fn fma_intrinsic<F>(
1053+
fn float_round_intrinsic<F>(
10421054
&mut self,
10431055
args: &[OpTy<'tcx, M::Provenance>],
10441056
dest: &PlaceTy<'tcx, M::Provenance>,
1057+
mode: rustc_apfloat::Round,
10451058
) -> InterpResult<'tcx, ()>
10461059
where
10471060
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
10481061
{
1049-
let a: F = self.read_scalar(&args[0])?.to_float()?;
1050-
let b: F = self.read_scalar(&args[1])?.to_float()?;
1051-
let c: F = self.read_scalar(&args[2])?.to_float()?;
1052-
1053-
let res = a.mul_add(b, c).value;
1054-
let res = self.adjust_nan(res, &[a, b, c]);
1062+
let res = self.float_round::<F>(self.read_scalar(&args[0])?, mode)?;
10551063
self.write_scalar(res, dest)?;
10561064
interp_ok(())
10571065
}
10581066

1067+
fn float_muladd<F>(
1068+
&self,
1069+
a: Scalar<M::Provenance>,
1070+
b: Scalar<M::Provenance>,
1071+
c: Scalar<M::Provenance>,
1072+
typ: MulAddType,
1073+
) -> InterpResult<'tcx, Scalar<M::Provenance>>
1074+
where
1075+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
1076+
{
1077+
let a: F = a.to_float()?;
1078+
let b: F = b.to_float()?;
1079+
let c: F = c.to_float()?;
1080+
1081+
let fuse = typ == MulAddType::Fused || M::float_fuse_mul_add(self);
1082+
1083+
let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value };
1084+
let res = self.adjust_nan(res, &[a, b, c]);
1085+
interp_ok(res.into())
1086+
}
1087+
10591088
fn float_muladd_intrinsic<F>(
10601089
&mut self,
10611090
args: &[OpTy<'tcx, M::Provenance>],
10621091
dest: &PlaceTy<'tcx, M::Provenance>,
1092+
typ: MulAddType,
10631093
) -> InterpResult<'tcx, ()>
10641094
where
10651095
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
10661096
{
1067-
let a: F = self.read_scalar(&args[0])?.to_float()?;
1068-
let b: F = self.read_scalar(&args[1])?.to_float()?;
1069-
let c: F = self.read_scalar(&args[2])?.to_float()?;
1070-
1071-
let fuse = M::float_fuse_mul_add(self);
1097+
let a = self.read_scalar(&args[0])?;
1098+
let b = self.read_scalar(&args[1])?;
1099+
let c = self.read_scalar(&args[2])?;
10721100

1073-
let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value };
1074-
let res = self.adjust_nan(res, &[a, b, c]);
1101+
let res = self.float_muladd::<F>(a, b, c, typ)?;
10751102
self.write_scalar(res, dest)?;
10761103
interp_ok(())
10771104
}

0 commit comments

Comments
 (0)