about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorJeremy Smart <jeremy3141592@gmail.com>2025-09-18 15:02:49 -0400
committerJeremy Smart <jeremy3141592@gmail.com>2025-09-24 15:21:31 -0400
commita00f24116e9bcecc8c73f9f7ec0c399964b37a92 (patch)
treefc7e41263808d8a95efbb5c906575a9eb37c236a /compiler/rustc_const_eval
parentce4beebecb77821734079cff47d8af08f9f27f11 (diff)
downloadrust-a00f24116e9bcecc8c73f9f7ec0c399964b37a92.tar.gz
rust-a00f24116e9bcecc8c73f9f7ec0c399964b37a92.zip
unstably constify float mul_add methods
Co-authored-by: Ralf Jung <post@ralfj.de>
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs46
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs8
2 files changed, 54 insertions, 0 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 418dd658121..785978b4d71 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -636,6 +636,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 dest,
                 rustc_apfloat::Round::NearestTiesToEven,
             )?,
+            sym::fmaf16 => self.fma_intrinsic::<Half>(args, dest)?,
+            sym::fmaf32 => self.fma_intrinsic::<Single>(args, dest)?,
+            sym::fmaf64 => self.fma_intrinsic::<Double>(args, dest)?,
+            sym::fmaf128 => self.fma_intrinsic::<Quad>(args, dest)?,
+            sym::fmuladdf16 => self.float_muladd_intrinsic::<Half>(args, dest)?,
+            sym::fmuladdf32 => self.float_muladd_intrinsic::<Single>(args, dest)?,
+            sym::fmuladdf64 => self.float_muladd_intrinsic::<Double>(args, dest)?,
+            sym::fmuladdf128 => self.float_muladd_intrinsic::<Quad>(args, dest)?,
 
             // Unsupported intrinsic: skip the return_to_block below.
             _ => return interp_ok(false),
@@ -1035,4 +1043,42 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         self.write_scalar(res, dest)?;
         interp_ok(())
     }
+
+    fn fma_intrinsic<F>(
+        &mut self,
+        args: &[OpTy<'tcx, M::Provenance>],
+        dest: &PlaceTy<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx, ()>
+    where
+        F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
+    {
+        let a: F = self.read_scalar(&args[0])?.to_float()?;
+        let b: F = self.read_scalar(&args[1])?.to_float()?;
+        let c: F = self.read_scalar(&args[2])?.to_float()?;
+
+        let res = a.mul_add(b, c).value;
+        let res = self.adjust_nan(res, &[a, b, c]);
+        self.write_scalar(res, dest)?;
+        interp_ok(())
+    }
+
+    fn float_muladd_intrinsic<F>(
+        &mut self,
+        args: &[OpTy<'tcx, M::Provenance>],
+        dest: &PlaceTy<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx, ()>
+    where
+        F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
+    {
+        let a: F = self.read_scalar(&args[0])?.to_float()?;
+        let b: F = self.read_scalar(&args[1])?.to_float()?;
+        let c: F = self.read_scalar(&args[2])?.to_float()?;
+
+        let fuse = M::float_fuse_mul_add(self);
+
+        let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value };
+        let res = self.adjust_nan(res, &[a, b, c]);
+        self.write_scalar(res, dest)?;
+        interp_ok(())
+    }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index e22629993fb..1725635e0b4 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -289,6 +289,9 @@ pub trait Machine<'tcx>: Sized {
         a
     }
 
+    /// Determines whether the `fmuladd` intrinsics fuse the multiply-add or use separate operations.
+    fn float_fuse_mul_add(_ecx: &mut InterpCx<'tcx, Self>) -> bool;
+
     /// Called before a basic block terminator is executed.
     #[inline]
     fn before_terminator(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
@@ -673,6 +676,11 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
     }
 
     #[inline(always)]
+    fn float_fuse_mul_add(_ecx: &mut InterpCx<$tcx, Self>) -> bool {
+        true
+    }
+
+    #[inline(always)]
     fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> {
         // We can't look at `tcx.sess` here as that can differ across crates, which can lead to
         // unsound differences in evaluating the same constant at different instantiation sites.