@@ -25,6 +25,15 @@ 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+
2837/// Directly returns an `Allocation` containing an absolute path representation of the given type.
2938pub ( crate ) fn alloc_type_name < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ( AllocId , u64 ) {
3039 let path = crate :: util:: type_name ( tcx, ty) ;
@@ -612,14 +621,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
612621 dest,
613622 rustc_apfloat:: Round :: NearestTiesToEven ,
614623 ) ?,
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+ }
623640
624641 // Unsupported intrinsic: skip the return_to_block below.
625642 _ => return interp_ok ( false ) ,
@@ -1020,40 +1037,41 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10201037 interp_ok ( ( ) )
10211038 }
10221039
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 >
10281047 where
10291048 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
10301049 {
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 ) ;
10341055
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 } ;
10361057 let res = self . adjust_nan ( res, & [ a, b, c] ) ;
1037- self . write_scalar ( res, dest) ?;
1038- interp_ok ( ( ) )
1058+ interp_ok ( res)
10391059 }
10401060
10411061 fn float_muladd_intrinsic < F > (
10421062 & mut self ,
10431063 args : & [ OpTy < ' tcx , M :: Provenance > ] ,
10441064 dest : & PlaceTy < ' tcx , M :: Provenance > ,
1065+ typ : MulAddType ,
10451066 ) -> InterpResult < ' tcx , ( ) >
10461067 where
10471068 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
10481069 {
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 ] ) ?;
10541073
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) ?;
10571075 self . write_scalar ( res, dest) ?;
10581076 interp_ok ( ( ) )
10591077 }
0 commit comments