diff options
Diffstat (limited to 'compiler/rustc_const_eval')
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/intrinsics.rs | 46 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/machine.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/util/caller_location.rs | 2 |
4 files changed, 55 insertions, 2 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. diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 8ace560d85d..9c0ec4e51a0 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(bootstrap, feature(strict_overflow_ops))] #![doc(rust_logo)] #![feature(array_try_map)] #![feature(assert_matches)] diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 5249b32eca4..4e7c8310007 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -61,7 +61,7 @@ pub(crate) fn const_caller_location_provider( trace!("const_caller_location: {}:{}:{}", file, line, col); let mut ecx = mk_eval_cx_to_read_const_val( tcx, - rustc_span::DUMMY_SP, // FIXME: use a proper span here? + rustc_span::DUMMY_SP, // This interpreter cannot fail, so the span is irrelevant. ty::TypingEnv::fully_monomorphized(), CanAccessMutGlobal::No, ); |
