@@ -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) ;
@@ -630,14 +639,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
630639 dest,
631640 rustc_apfloat:: Round :: NearestTiesToEven ,
632641 ) ?,
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) ?,
642+ sym:: fmaf16 => self . float_muladd_intrinsic :: < Half > ( args, dest, MulAddType :: Fused ) ?,
643+ sym:: fmaf32 => self . float_muladd_intrinsic :: < Single > ( args, dest, MulAddType :: Fused ) ?,
644+ sym:: fmaf64 => self . float_muladd_intrinsic :: < Double > ( args, dest, MulAddType :: Fused ) ?,
645+ sym:: fmaf128 => self . float_muladd_intrinsic :: < Quad > ( args, dest, MulAddType :: Fused ) ?,
646+ sym:: fmuladdf16 => {
647+ self . float_muladd_intrinsic :: < Half > ( args, dest, MulAddType :: Nondeterministic ) ?
648+ }
649+ sym:: fmuladdf32 => {
650+ self . float_muladd_intrinsic :: < Single > ( args, dest, MulAddType :: Nondeterministic ) ?
651+ }
652+ sym:: fmuladdf64 => {
653+ self . float_muladd_intrinsic :: < Double > ( args, dest, MulAddType :: Nondeterministic ) ?
654+ }
655+ sym:: fmuladdf128 => {
656+ self . float_muladd_intrinsic :: < Quad > ( args, dest, MulAddType :: Nondeterministic ) ?
657+ }
641658
642659 // Unsupported intrinsic: skip the return_to_block below.
643660 _ => return interp_ok ( false ) ,
@@ -1038,40 +1055,41 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10381055 interp_ok ( ( ) )
10391056 }
10401057
1041- fn fma_intrinsic < F > (
1042- & mut self ,
1043- args : & [ OpTy < ' tcx , M :: Provenance > ] ,
1044- dest : & PlaceTy < ' tcx , M :: Provenance > ,
1045- ) -> InterpResult < ' tcx , ( ) >
1058+ fn float_muladd < F > (
1059+ & self ,
1060+ a : Scalar < M :: Provenance > ,
1061+ b : Scalar < M :: Provenance > ,
1062+ c : Scalar < M :: Provenance > ,
1063+ typ : MulAddType ,
1064+ ) -> InterpResult < ' tcx , Scalar < M :: Provenance > >
10461065 where
10471066 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
10481067 {
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 ( ) ?;
1068+ let a: F = a. to_float ( ) ?;
1069+ let b: F = b. to_float ( ) ?;
1070+ let c: F = c. to_float ( ) ?;
1071+
1072+ let fuse = typ == MulAddType :: Fused || M :: float_fuse_mul_add ( self ) ;
10521073
1053- let res = a. mul_add ( b, c) . value ;
1074+ let res = if fuse { a. mul_add ( b, c) . value } else { ( ( a * b ) . value + c ) . value } ;
10541075 let res = self . adjust_nan ( res, & [ a, b, c] ) ;
1055- self . write_scalar ( res, dest) ?;
1056- interp_ok ( ( ) )
1076+ interp_ok ( res. into ( ) )
10571077 }
10581078
10591079 fn float_muladd_intrinsic < F > (
10601080 & mut self ,
10611081 args : & [ OpTy < ' tcx , M :: Provenance > ] ,
10621082 dest : & PlaceTy < ' tcx , M :: Provenance > ,
1083+ typ : MulAddType ,
10631084 ) -> InterpResult < ' tcx , ( ) >
10641085 where
10651086 F : rustc_apfloat:: Float + rustc_apfloat:: FloatConvert < F > + Into < Scalar < M :: Provenance > > ,
10661087 {
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 ) ;
1088+ let a = self . read_scalar ( & args[ 0 ] ) ?;
1089+ let b = self . read_scalar ( & args[ 1 ] ) ?;
1090+ let c = self . read_scalar ( & args[ 2 ] ) ?;
10721091
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] ) ;
1092+ let res = self . float_muladd :: < F > ( a, b, c, typ) ?;
10751093 self . write_scalar ( res, dest) ?;
10761094 interp_ok ( ( ) )
10771095 }
0 commit comments