@@ -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) ;
@@ -513,25 +529,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
513529 self . write_scalar ( Scalar :: from_target_usize ( align. bytes ( ) , self ) , dest) ?;
514530 }
515531
516- sym:: minnumf16 => self . float_min_intrinsic :: < Half > ( args, dest) ?,
517- sym:: minnumf32 => self . float_min_intrinsic :: < Single > ( args, dest) ?,
518- sym:: minnumf64 => self . float_min_intrinsic :: < Double > ( args, dest) ?,
519- sym:: minnumf128 => self . float_min_intrinsic :: < Quad > ( args, dest) ?,
532+ sym:: minnumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: MinNum , dest) ?,
533+ sym:: minnumf32 => self . float_minmax_intrinsic :: < Single > ( args, MinMax :: MinNum , dest) ?,
534+ sym:: minnumf64 => self . float_minmax_intrinsic :: < Double > ( args, MinMax :: MinNum , dest) ?,
535+ sym:: minnumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: MinNum , dest) ?,
520536
521- sym:: minimumf16 => self . float_minimum_intrinsic :: < Half > ( args, dest) ?,
522- sym:: minimumf32 => self . float_minimum_intrinsic :: < Single > ( args, dest) ?,
523- sym:: minimumf64 => self . float_minimum_intrinsic :: < Double > ( args, dest) ?,
524- sym:: minimumf128 => self . float_minimum_intrinsic :: < Quad > ( args, dest) ?,
537+ sym:: minimumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: Minimum , dest) ?,
538+ sym:: minimumf32 => {
539+ self . float_minmax_intrinsic :: < Single > ( args, MinMax :: Minimum , dest) ?
540+ }
541+ sym:: minimumf64 => {
542+ self . float_minmax_intrinsic :: < Double > ( args, MinMax :: Minimum , dest) ?
543+ }
544+ sym:: minimumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: Minimum , dest) ?,
525545
526- sym:: maxnumf16 => self . float_max_intrinsic :: < Half > ( args, dest) ?,
527- sym:: maxnumf32 => self . float_max_intrinsic :: < Single > ( args, dest) ?,
528- sym:: maxnumf64 => self . float_max_intrinsic :: < Double > ( args, dest) ?,
529- sym:: maxnumf128 => self . float_max_intrinsic :: < Quad > ( args, dest) ?,
546+ sym:: maxnumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: MaxNum , dest) ?,
547+ sym:: maxnumf32 => self . float_minmax_intrinsic :: < Single > ( args, MinMax :: MaxNum , dest) ?,
548+ sym:: maxnumf64 => self . float_minmax_intrinsic :: < Double > ( args, MinMax :: MaxNum , dest) ?,
549+ sym:: maxnumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: MaxNum , dest) ?,
530550
531- sym:: maximumf16 => self . float_maximum_intrinsic :: < Half > ( args, dest) ?,
532- sym:: maximumf32 => self . float_maximum_intrinsic :: < Single > ( args, dest) ?,
533- sym:: maximumf64 => self . float_maximum_intrinsic :: < Double > ( args, dest) ?,
534- sym:: maximumf128 => self . float_maximum_intrinsic :: < Quad > ( args, dest) ?,
551+ sym:: maximumf16 => self . float_minmax_intrinsic :: < Half > ( args, MinMax :: Maximum , dest) ?,
552+ sym:: maximumf32 => {
553+ self . float_minmax_intrinsic :: < Single > ( args, MinMax :: Maximum , dest) ?
554+ }
555+ sym:: maximumf64 => {
556+ self . float_minmax_intrinsic :: < Double > ( args, MinMax :: Maximum , dest) ?
557+ }
558+ sym:: maximumf128 => self . float_minmax_intrinsic :: < Quad > ( args, MinMax :: Maximum , dest) ?,
535559
536560 sym:: copysignf16 => self . float_copysign_intrinsic :: < Half > ( args, dest) ?,
537561 sym:: copysignf32 => self . float_copysign_intrinsic :: < Single > ( args, dest) ?,
@@ -936,76 +960,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
936960 interp_ok ( Scalar :: from_bool ( lhs_bytes == rhs_bytes) )
937961 }
938962
939- fn float_min_intrinsic < F > (
940- & mut self ,
941- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
942- dest : & PlaceTy < ' tcx , M :: Provenance > ,
943- ) -> InterpResult < ' tcx , ( ) >
944- where
945- F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
946- {
947- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
948- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
949- let res = if a == b {
950- // They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
951- // Let the machine decide which one to return.
952- M :: equal_float_min_max ( self , a, b)
953- } else {
954- self . adjust_nan ( a. min ( b) , & [ a, b] )
955- } ;
956- self . write_scalar ( res, dest) ?;
957- interp_ok ( ( ) )
958- }
959-
960- fn float_max_intrinsic < F > (
961- & mut self ,
962- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
963- dest : & PlaceTy < ' tcx , M :: Provenance > ,
964- ) -> InterpResult < ' tcx , ( ) >
963+ fn float_minmax < F > (
964+ & self ,
965+ a : Scalar < M :: Provenance > ,
966+ b : Scalar < M :: Provenance > ,
967+ op : MinMax ,
968+ ) -> InterpResult < ' tcx , Scalar < M :: Provenance > >
965969 where
966970 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
967971 {
968- let a: F = self . read_scalar ( & args [ 0 ] ) ? . to_float ( ) ?;
969- let b: F = self . read_scalar ( & args [ 1 ] ) ? . to_float ( ) ?;
970- let res = if a == b {
972+ let a: F = a . to_float ( ) ?;
973+ let b: F = b . to_float ( ) ?;
974+ let res = if matches ! ( op , MinMax :: MinNum | MinMax :: MaxNum ) && a == b {
971975 // They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
972976 // Let the machine decide which one to return.
973977 M :: equal_float_min_max ( self , a, b)
974978 } else {
975- self . adjust_nan ( a. max ( b) , & [ a, b] )
979+ let result = match op {
980+ MinMax :: Minimum => a. minimum ( b) ,
981+ MinMax :: MinNum => a. min ( b) ,
982+ MinMax :: Maximum => a. maximum ( b) ,
983+ MinMax :: MaxNum => a. max ( b) ,
984+ } ;
985+ self . adjust_nan ( result, & [ a, b] )
976986 } ;
977- self . write_scalar ( res, dest) ?;
978- interp_ok ( ( ) )
979- }
980987
981- fn float_minimum_intrinsic < F > (
982- & mut self ,
983- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
984- dest : & PlaceTy < ' tcx , M :: Provenance > ,
985- ) -> InterpResult < ' tcx , ( ) >
986- where
987- F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
988- {
989- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
990- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
991- let res = a. minimum ( b) ;
992- let res = self . adjust_nan ( res, & [ a, b] ) ;
993- self . write_scalar ( res, dest) ?;
994- interp_ok ( ( ) )
988+ interp_ok ( res. into ( ) )
995989 }
996990
997- fn float_maximum_intrinsic < F > (
991+ fn float_minmax_intrinsic < F > (
998992 & mut self ,
999993 args : & [ OpTy < ' tcx , M :: Provenance > ] ,
994+ op : MinMax ,
1000995 dest : & PlaceTy < ' tcx , M :: Provenance > ,
1001996 ) -> InterpResult < ' tcx , ( ) >
1002997 where
1003998 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
1004999 {
1005- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
1006- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
1007- let res = a. maximum ( b) ;
1008- let res = self . adjust_nan ( res, & [ a, b] ) ;
1000+ let res =
1001+ self . float_minmax :: < F > ( self . read_scalar ( & args[ 0 ] ) ?, self . read_scalar ( & args[ 1 ] ) ?, op) ?;
10091002 self . write_scalar ( res, dest) ?;
10101003 interp_ok ( ( ) )
10111004 }
0 commit comments