@@ -34,6 +34,22 @@ enum MulAddType {
3434 Nondeterministic ,
3535}
3636
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`.
41+ Minimum ,
42+ /// The IEEE `MinNum` operation - see `f32::min` etc
43+ /// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic.
44+ MinNum ,
45+ /// The IEEE `Maximum` operation - see `f32::maximum` etc
46+ /// In particular, `-0.0` is considered smaller than `+0.0`.
47+ Maximum ,
48+ /// The IEEE `MaxNum` operation - see `f32::max` etc
49+ /// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic.
50+ MaxNum ,
51+ }
52+
3753/// Directly returns an `Allocation` containing an absolute path representation of the given type.
3854pub ( crate ) fn alloc_type_name < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ( AllocId , u64 ) {
3955 let path = crate :: util:: type_name ( tcx, ty) ;
@@ -495,25 +511,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
495511 self . write_scalar ( Scalar :: from_target_usize ( align. bytes ( ) , self ) , dest) ?;
496512 }
497513
498- sym:: minnumf16 => self . float_min_intrinsic :: < Half > ( args, dest) ?,
499- sym:: minnumf32 => self . float_min_intrinsic :: < Single > ( args, dest) ?,
500- sym:: minnumf64 => self . float_min_intrinsic :: < Double > ( args, dest) ?,
501- sym:: minnumf128 => self . float_min_intrinsic :: < Quad > ( args, dest) ?,
514+ sym:: minnumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: MinNum , dest) ?,
515+ sym:: minnumf32 => self . float_minmax_intrinsic :: < Single > ( args, MinMax :: MinNum , dest) ?,
516+ sym:: minnumf64 => self . float_minmax_intrinsic :: < Double > ( args, MinMax :: MinNum , dest) ?,
517+ sym:: minnumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: MinNum , dest) ?,
502518
503- sym:: minimumf16 => self . float_minimum_intrinsic :: < Half > ( args, dest) ?,
504- sym:: minimumf32 => self . float_minimum_intrinsic :: < Single > ( args, dest) ?,
505- sym:: minimumf64 => self . float_minimum_intrinsic :: < Double > ( args, dest) ?,
506- sym:: minimumf128 => self . float_minimum_intrinsic :: < Quad > ( args, dest) ?,
519+ sym:: minimumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: Minimum , dest) ?,
520+ sym:: minimumf32 => {
521+ self . float_minmax_intrinsic :: < Single > ( args, MinMax :: Minimum , dest) ?
522+ }
523+ sym:: minimumf64 => {
524+ self . float_minmax_intrinsic :: < Double > ( args, MinMax :: Minimum , dest) ?
525+ }
526+ sym:: minimumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: Minimum , dest) ?,
507527
508- sym:: maxnumf16 => self . float_max_intrinsic :: < Half > ( args, dest) ?,
509- sym:: maxnumf32 => self . float_max_intrinsic :: < Single > ( args, dest) ?,
510- sym:: maxnumf64 => self . float_max_intrinsic :: < Double > ( args, dest) ?,
511- sym:: maxnumf128 => self . float_max_intrinsic :: < Quad > ( args, dest) ?,
528+ sym:: maxnumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: MaxNum , dest) ?,
529+ sym:: maxnumf32 => self . float_minmax_intrinsic :: < Single > ( args, MinMax :: MaxNum , dest) ?,
530+ sym:: maxnumf64 => self . float_minmax_intrinsic :: < Double > ( args, MinMax :: MaxNum , dest) ?,
531+ sym:: maxnumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: MaxNum , dest) ?,
512532
513- sym:: maximumf16 => self . float_maximum_intrinsic :: < Half > ( args, dest) ?,
514- sym:: maximumf32 => self . float_maximum_intrinsic :: < Single > ( args, dest) ?,
515- sym:: maximumf64 => self . float_maximum_intrinsic :: < Double > ( args, dest) ?,
516- sym:: maximumf128 => self . float_maximum_intrinsic :: < Quad > ( args, dest) ?,
533+ sym:: maximumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: Maximum , dest) ?,
534+ sym:: maximumf32 => {
535+ self . float_minmax_intrinsic :: < Single > ( args, MinMax :: Maximum , dest) ?
536+ }
537+ sym:: maximumf64 => {
538+ self . float_minmax_intrinsic :: < Double > ( args, MinMax :: Maximum , dest) ?
539+ }
540+ sym:: maximumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: Maximum , dest) ?,
517541
518542 sym:: copysignf16 => self . float_copysign_intrinsic :: < Half > ( args, dest) ?,
519543 sym:: copysignf32 => self . float_copysign_intrinsic :: < Single > ( args, dest) ?,
@@ -918,76 +942,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
918942 interp_ok ( Scalar :: from_bool ( lhs_bytes == rhs_bytes) )
919943 }
920944
921- fn float_min_intrinsic < F > (
922- & mut self ,
923- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
924- dest : & PlaceTy < ' tcx , M :: Provenance > ,
925- ) -> InterpResult < ' tcx , ( ) >
926- where
927- F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
928- {
929- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
930- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
931- let res = if a == b {
932- // They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
933- // Let the machine decide which one to return.
934- M :: equal_float_min_max ( self , a, b)
935- } else {
936- self . adjust_nan ( a. min ( b) , & [ a, b] )
937- } ;
938- self . write_scalar ( res, dest) ?;
939- interp_ok ( ( ) )
940- }
941-
942- fn float_max_intrinsic < F > (
943- & mut self ,
944- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
945- dest : & PlaceTy < ' tcx , M :: Provenance > ,
946- ) -> InterpResult < ' tcx , ( ) >
945+ fn float_minmax < F > (
946+ & self ,
947+ a : Scalar < M :: Provenance > ,
948+ b : Scalar < M :: Provenance > ,
949+ op : MinMax ,
950+ ) -> InterpResult < ' tcx , Scalar < M :: Provenance > >
947951 where
948952 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
949953 {
950- let a: F = self . read_scalar ( & args [ 0 ] ) ? . to_float ( ) ?;
951- let b: F = self . read_scalar ( & args [ 1 ] ) ? . to_float ( ) ?;
952- let res = if a == b {
954+ let a: F = a . to_float ( ) ?;
955+ let b: F = b . to_float ( ) ?;
956+ let res = if matches ! ( op , MinMax :: MinNum | MinMax :: MaxNum ) && a == b {
953957 // They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
954958 // Let the machine decide which one to return.
955959 M :: equal_float_min_max ( self , a, b)
956960 } else {
957- self . adjust_nan ( a. max ( b) , & [ a, b] )
961+ let result = match op {
962+ MinMax :: Minimum => a. minimum ( b) ,
963+ MinMax :: MinNum => a. min ( b) ,
964+ MinMax :: Maximum => a. maximum ( b) ,
965+ MinMax :: MaxNum => a. max ( b) ,
966+ } ;
967+ self . adjust_nan ( result, & [ a, b] )
958968 } ;
959- self . write_scalar ( res, dest) ?;
960- interp_ok ( ( ) )
961- }
962969
963- fn float_minimum_intrinsic < F > (
964- & mut self ,
965- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
966- dest : & PlaceTy < ' tcx , M :: Provenance > ,
967- ) -> InterpResult < ' tcx , ( ) >
968- where
969- F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
970- {
971- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
972- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
973- let res = a. minimum ( b) ;
974- let res = self . adjust_nan ( res, & [ a, b] ) ;
975- self . write_scalar ( res, dest) ?;
976- interp_ok ( ( ) )
970+ interp_ok ( res. into ( ) )
977971 }
978972
979- fn float_maximum_intrinsic < F > (
973+ fn float_minmax_intrinsic < F > (
980974 & mut self ,
981975 args : & [ OpTy < ' tcx , M :: Provenance > ] ,
976+ op : MinMax ,
982977 dest : & PlaceTy < ' tcx , M :: Provenance > ,
983978 ) -> InterpResult < ' tcx , ( ) >
984979 where
985980 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
986981 {
987- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
988- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
989- let res = a. maximum ( b) ;
990- let res = self . adjust_nan ( res, & [ a, b] ) ;
982+ let res =
983+ self . float_minmax :: < F > ( self . read_scalar ( & args[ 0 ] ) ?, self . read_scalar ( & args[ 1 ] ) ?, op) ?;
991984 self . write_scalar ( res, dest) ?;
992985 interp_ok ( ( ) )
993986 }
0 commit comments