@@ -34,6 +34,22 @@ enum MulAddType {
34
34
Nondeterministic ,
35
35
}
36
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`.
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
+
37
53
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
38
54
pub ( crate ) fn alloc_type_name < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ( AllocId , u64 ) {
39
55
let path = crate :: util:: type_name ( tcx, ty) ;
@@ -495,25 +511,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
495
511
self . write_scalar ( Scalar :: from_target_usize ( align. bytes ( ) , self ) , dest) ?;
496
512
}
497
513
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) ?,
502
518
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) ?,
507
527
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) ?,
512
532
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) ?,
517
541
518
542
sym:: copysignf16 => self . float_copysign_intrinsic :: < Half > ( args, dest) ?,
519
543
sym:: copysignf32 => self . float_copysign_intrinsic :: < Single > ( args, dest) ?,
@@ -918,76 +942,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
918
942
interp_ok ( Scalar :: from_bool ( lhs_bytes == rhs_bytes) )
919
943
}
920
944
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 > >
947
951
where
948
952
F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
949
953
{
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 {
953
957
// They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
954
958
// Let the machine decide which one to return.
955
959
M :: equal_float_min_max ( self , a, b)
956
960
} 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] )
958
968
} ;
959
- self . write_scalar ( res, dest) ?;
960
- interp_ok ( ( ) )
961
- }
962
969
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 ( ) )
977
971
}
978
972
979
- fn float_maximum_intrinsic < F > (
973
+ fn float_minmax_intrinsic < F > (
980
974
& mut self ,
981
975
args : & [ OpTy < ' tcx , M :: Provenance > ] ,
976
+ op : MinMax ,
982
977
dest : & PlaceTy < ' tcx , M :: Provenance > ,
983
978
) -> InterpResult < ' tcx , ( ) >
984
979
where
985
980
F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
986
981
{
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) ?;
991
984
self . write_scalar ( res, dest) ?;
992
985
interp_ok ( ( ) )
993
986
}
0 commit comments