@@ -25,6 +25,15 @@ use super::{
25
25
} ;
26
26
use crate :: fluent_generated as fluent;
27
27
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
+
28
37
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
29
38
pub ( crate ) fn alloc_type_name < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ( AllocId , u64 ) {
30
39
let path = crate :: util:: type_name ( tcx, ty) ;
@@ -612,14 +621,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
612
621
dest,
613
622
rustc_apfloat:: Round :: NearestTiesToEven ,
614
623
) ?,
615
- sym:: fmaf16 => self . fma_intrinsic :: < Half > ( args, dest) ?,
616
- sym:: fmaf32 => self . fma_intrinsic :: < Single > ( args, dest) ?,
617
- sym:: fmaf64 => self . fma_intrinsic :: < Double > ( args, dest) ?,
618
- sym:: fmaf128 => self . fma_intrinsic :: < Quad > ( args, dest) ?,
619
- sym:: fmuladdf16 => self . float_muladd_intrinsic :: < Half > ( args, dest) ?,
620
- sym:: fmuladdf32 => self . float_muladd_intrinsic :: < Single > ( args, dest) ?,
621
- sym:: fmuladdf64 => self . float_muladd_intrinsic :: < Double > ( args, dest) ?,
622
- sym:: fmuladdf128 => self . float_muladd_intrinsic :: < Quad > ( args, dest) ?,
624
+ sym:: fmaf16 => self . float_muladd_intrinsic :: < Half > ( args, dest, MulAddType :: Fused ) ?,
625
+ sym:: fmaf32 => self . float_muladd_intrinsic :: < Single > ( args, dest, MulAddType :: Fused ) ?,
626
+ sym:: fmaf64 => self . float_muladd_intrinsic :: < Double > ( args, dest, MulAddType :: Fused ) ?,
627
+ sym:: fmaf128 => self . float_muladd_intrinsic :: < Quad > ( args, dest, MulAddType :: Fused ) ?,
628
+ sym:: fmuladdf16 => {
629
+ self . float_muladd_intrinsic :: < Half > ( args, dest, MulAddType :: Nondeterministic ) ?
630
+ }
631
+ sym:: fmuladdf32 => {
632
+ self . float_muladd_intrinsic :: < Single > ( args, dest, MulAddType :: Nondeterministic ) ?
633
+ }
634
+ sym:: fmuladdf64 => {
635
+ self . float_muladd_intrinsic :: < Double > ( args, dest, MulAddType :: Nondeterministic ) ?
636
+ }
637
+ sym:: fmuladdf128 => {
638
+ self . float_muladd_intrinsic :: < Quad > ( args, dest, MulAddType :: Nondeterministic ) ?
639
+ }
623
640
624
641
// Unsupported intrinsic: skip the return_to_block below.
625
642
_ => return interp_ok ( false ) ,
@@ -1020,40 +1037,41 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1020
1037
interp_ok ( ( ) )
1021
1038
}
1022
1039
1023
- fn fma_intrinsic < F > (
1024
- & mut self ,
1025
- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
1026
- dest : & PlaceTy < ' tcx , M :: Provenance > ,
1027
- ) -> InterpResult < ' tcx , ( ) >
1040
+ fn float_muladd < F > (
1041
+ & self ,
1042
+ a : Scalar < M :: Provenance > ,
1043
+ b : Scalar < M :: Provenance > ,
1044
+ c : Scalar < M :: Provenance > ,
1045
+ typ : MulAddType ,
1046
+ ) -> InterpResult < ' tcx , F >
1028
1047
where
1029
1048
F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
1030
1049
{
1031
- let a: F = self . read_scalar ( & args[ 0 ] ) ?. to_float ( ) ?;
1032
- let b: F = self . read_scalar ( & args[ 1 ] ) ?. to_float ( ) ?;
1033
- let c: F = self . read_scalar ( & args[ 2 ] ) ?. to_float ( ) ?;
1050
+ let a: F = a. to_float ( ) ?;
1051
+ let b: F = b. to_float ( ) ?;
1052
+ let c: F = c. to_float ( ) ?;
1053
+
1054
+ let fuse = typ == MulAddType :: Fused || M :: float_fuse_mul_add ( self ) ;
1034
1055
1035
- let res = a. mul_add ( b, c) . value ;
1056
+ let res = if fuse { a. mul_add ( b, c) . value } else { ( ( a * b ) . value + c ) . value } ;
1036
1057
let res = self . adjust_nan ( res, & [ a, b, c] ) ;
1037
- self . write_scalar ( res, dest) ?;
1038
- interp_ok ( ( ) )
1058
+ interp_ok ( res)
1039
1059
}
1040
1060
1041
1061
fn float_muladd_intrinsic < F > (
1042
1062
& mut self ,
1043
1063
args : & [ OpTy < ' tcx , M :: Provenance > ] ,
1044
1064
dest : & PlaceTy < ' tcx , M :: Provenance > ,
1065
+ typ : MulAddType ,
1045
1066
) -> InterpResult < ' tcx , ( ) >
1046
1067
where
1047
1068
F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
1048
1069
{
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 fuse = M :: float_fuse_mul_add ( self ) ;
1070
+ let a = self . read_scalar ( & args[ 0 ] ) ?;
1071
+ let b = self . read_scalar ( & args[ 1 ] ) ?;
1072
+ let c = self . read_scalar ( & args[ 2 ] ) ?;
1054
1073
1055
- let res = if fuse { a. mul_add ( b, c) . value } else { ( ( a * b) . value + c) . value } ;
1056
- let res = self . adjust_nan ( res, & [ a, b, c] ) ;
1074
+ let res = self . float_muladd :: < F > ( a, b, c, typ) ?;
1057
1075
self . write_scalar ( res, dest) ?;
1058
1076
interp_ok ( ( ) )
1059
1077
}
0 commit comments