@@ -25,6 +25,35 @@ use super::{
2525} ;
2626use 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.
2958pub ( 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