@@ -34,6 +34,26 @@ 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` 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+
3757/// Directly returns an `Allocation` containing an absolute path representation of the given type.
3858pub ( crate ) fn alloc_type_name < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ( AllocId , u64 ) {
3959 let path = crate :: util:: type_name ( tcx, ty) ;
@@ -513,25 +533,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
513533 self . write_scalar ( Scalar :: from_target_usize ( align. bytes ( ) , self ) , dest) ?;
514534 }
515535
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) ?,
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) ?,
520540
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) ?,
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) ?,
525549
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) ?,
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) ?,
530554
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) ?,
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) ?,
535563
536564 sym:: copysignf16 => self . float_copysign_intrinsic :: < Half > ( args, dest) ?,
537565 sym:: copysignf32 => self . float_copysign_intrinsic :: < Single > ( args, dest) ?,
@@ -936,76 +964,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
936964 interp_ok ( Scalar :: from_bool ( lhs_bytes == rhs_bytes) )
937965 }
938966
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 , ( ) >
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 > >
965973 where
966974 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
967975 {
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 {
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 {
971979 // They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
972980 // Let the machine decide which one to return.
973981 M :: equal_float_min_max ( self , a, b)
974982 } else {
975- 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] )
976990 } ;
977- self . write_scalar ( res, dest) ?;
978- interp_ok ( ( ) )
979- }
980991
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 ( ( ) )
992+ interp_ok ( res. into ( ) )
995993 }
996994
997- fn float_maximum_intrinsic < F > (
995+ fn float_minmax_intrinsic < F > (
998996 & mut self ,
999997 args : & [ OpTy < ' tcx , M :: Provenance > ] ,
998+ op : MinMax ,
1000999 dest : & PlaceTy < ' tcx , M :: Provenance > ,
10011000 ) -> InterpResult < ' tcx , ( ) >
10021001 where
10031002 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
10041003 {
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] ) ;
1004+ let res =
1005+ self . float_minmax :: < F > ( self . read_scalar ( & args[ 0 ] ) ?, self . read_scalar ( & args[ 1 ] ) ?, op) ?;
10091006 self . write_scalar ( res, dest) ?;
10101007 interp_ok ( ( ) )
10111008 }
0 commit comments