diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-09-25 20:31:54 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-25 20:31:54 +1000 |
| commit | 8e62f95376e40f3eb81e5f1b29cb4eb997c36fb5 (patch) | |
| tree | b2d69fb08a5da2318f88e50c6fe4fbe87400dc49 /compiler/rustc_const_eval/src | |
| parent | fab06469ee33664739620ede53ed18b8c3c40644 (diff) | |
| parent | a00f24116e9bcecc8c73f9f7ec0c399964b37a92 (diff) | |
| download | rust-8e62f95376e40f3eb81e5f1b29cb4eb997c36fb5.tar.gz rust-8e62f95376e40f3eb81e5f1b29cb4eb997c36fb5.zip | |
Rollup merge of #146735 - Qelxiros:const_mul_add, r=tgross35,RalfJung
unstably constify float mul_add methods Tracking issue: rust-lang/rust#146724 r? `@tgross35`
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/intrinsics.rs | 46 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/machine.rs | 8 |
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. |
