|
1 |
| -use rustc_apfloat::{ieee::Single, Float as _}; |
| 1 | +use rustc_apfloat::ieee::Single; |
2 | 2 | use rustc_middle::mir;
|
3 | 3 | use rustc_span::Symbol;
|
4 | 4 | use rustc_target::spec::abi::Abi;
|
5 | 5 |
|
6 |
| -use rand::Rng as _; |
7 |
| - |
8 |
| -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp}; |
| 6 | +use super::{ |
| 7 | + bin_op_simd_float_all, bin_op_simd_float_first, unary_op_ps, unary_op_ss, FloatBinOp, |
| 8 | + FloatUnaryOp, |
| 9 | +}; |
9 | 10 | use crate::*;
|
10 | 11 | use shims::foreign_items::EmulateForeignItemResult;
|
11 | 12 |
|
@@ -219,124 +220,3 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
219 | 220 | Ok(EmulateForeignItemResult::NeedsJumping)
|
220 | 221 | }
|
221 | 222 | }
|
222 |
| - |
223 |
| -#[derive(Copy, Clone)] |
224 |
| -enum FloatUnaryOp { |
225 |
| - /// sqrt(x) |
226 |
| - /// |
227 |
| - /// <https://www.felixcloutier.com/x86/sqrtss> |
228 |
| - /// <https://www.felixcloutier.com/x86/sqrtps> |
229 |
| - Sqrt, |
230 |
| - /// Approximation of 1/x |
231 |
| - /// |
232 |
| - /// <https://www.felixcloutier.com/x86/rcpss> |
233 |
| - /// <https://www.felixcloutier.com/x86/rcpps> |
234 |
| - Rcp, |
235 |
| - /// Approximation of 1/sqrt(x) |
236 |
| - /// |
237 |
| - /// <https://www.felixcloutier.com/x86/rsqrtss> |
238 |
| - /// <https://www.felixcloutier.com/x86/rsqrtps> |
239 |
| - Rsqrt, |
240 |
| -} |
241 |
| - |
242 |
| -/// Performs `which` scalar operation on `op` and returns the result. |
243 |
| -#[allow(clippy::arithmetic_side_effects)] // floating point operations without side effects |
244 |
| -fn unary_op_f32<'tcx>( |
245 |
| - this: &mut crate::MiriInterpCx<'_, 'tcx>, |
246 |
| - which: FloatUnaryOp, |
247 |
| - op: &ImmTy<'tcx, Provenance>, |
248 |
| -) -> InterpResult<'tcx, Scalar<Provenance>> { |
249 |
| - match which { |
250 |
| - FloatUnaryOp::Sqrt => { |
251 |
| - let op = op.to_scalar(); |
252 |
| - // FIXME using host floats |
253 |
| - Ok(Scalar::from_u32(f32::from_bits(op.to_u32()?).sqrt().to_bits())) |
254 |
| - } |
255 |
| - FloatUnaryOp::Rcp => { |
256 |
| - let op = op.to_scalar().to_f32()?; |
257 |
| - let div = (Single::from_u128(1).value / op).value; |
258 |
| - // Apply a relative error with a magnitude on the order of 2^-12 to simulate the |
259 |
| - // inaccuracy of RCP. |
260 |
| - let res = apply_random_float_error(this, div, -12); |
261 |
| - Ok(Scalar::from_f32(res)) |
262 |
| - } |
263 |
| - FloatUnaryOp::Rsqrt => { |
264 |
| - let op = op.to_scalar().to_u32()?; |
265 |
| - // FIXME using host floats |
266 |
| - let sqrt = Single::from_bits(f32::from_bits(op).sqrt().to_bits().into()); |
267 |
| - let rsqrt = (Single::from_u128(1).value / sqrt).value; |
268 |
| - // Apply a relative error with a magnitude on the order of 2^-12 to simulate the |
269 |
| - // inaccuracy of RSQRT. |
270 |
| - let res = apply_random_float_error(this, rsqrt, -12); |
271 |
| - Ok(Scalar::from_f32(res)) |
272 |
| - } |
273 |
| - } |
274 |
| -} |
275 |
| - |
276 |
| -/// Disturbes a floating-point result by a relative error on the order of (-2^scale, 2^scale). |
277 |
| -#[allow(clippy::arithmetic_side_effects)] // floating point arithmetic cannot panic |
278 |
| -fn apply_random_float_error<F: rustc_apfloat::Float>( |
279 |
| - this: &mut crate::MiriInterpCx<'_, '_>, |
280 |
| - val: F, |
281 |
| - err_scale: i32, |
282 |
| -) -> F { |
283 |
| - let rng = this.machine.rng.get_mut(); |
284 |
| - // generates rand(0, 2^64) * 2^(scale - 64) = rand(0, 1) * 2^scale |
285 |
| - let err = |
286 |
| - F::from_u128(rng.gen::<u64>().into()).value.scalbn(err_scale.checked_sub(64).unwrap()); |
287 |
| - // give it a random sign |
288 |
| - let err = if rng.gen::<bool>() { -err } else { err }; |
289 |
| - // multiple the value with (1+err) |
290 |
| - (val * (F::from_u128(1).value + err).value).value |
291 |
| -} |
292 |
| - |
293 |
| -/// Performs `which` operation on the first component of `op` and copies |
294 |
| -/// the other components. The result is stored in `dest`. |
295 |
| -fn unary_op_ss<'tcx>( |
296 |
| - this: &mut crate::MiriInterpCx<'_, 'tcx>, |
297 |
| - which: FloatUnaryOp, |
298 |
| - op: &OpTy<'tcx, Provenance>, |
299 |
| - dest: &PlaceTy<'tcx, Provenance>, |
300 |
| -) -> InterpResult<'tcx, ()> { |
301 |
| - let (op, op_len) = this.operand_to_simd(op)?; |
302 |
| - let (dest, dest_len) = this.place_to_simd(dest)?; |
303 |
| - |
304 |
| - assert_eq!(dest_len, op_len); |
305 |
| - |
306 |
| - let res0 = unary_op_f32(this, which, &this.read_immediate(&this.project_index(&op, 0)?)?)?; |
307 |
| - this.write_scalar(res0, &this.project_index(&dest, 0)?)?; |
308 |
| - |
309 |
| - for i in 1..dest_len { |
310 |
| - this.copy_op( |
311 |
| - &this.project_index(&op, i)?, |
312 |
| - &this.project_index(&dest, i)?, |
313 |
| - /*allow_transmute*/ false, |
314 |
| - )?; |
315 |
| - } |
316 |
| - |
317 |
| - Ok(()) |
318 |
| -} |
319 |
| - |
320 |
| -/// Performs `which` operation on each component of `op`, storing the |
321 |
| -/// result is stored in `dest`. |
322 |
| -fn unary_op_ps<'tcx>( |
323 |
| - this: &mut crate::MiriInterpCx<'_, 'tcx>, |
324 |
| - which: FloatUnaryOp, |
325 |
| - op: &OpTy<'tcx, Provenance>, |
326 |
| - dest: &PlaceTy<'tcx, Provenance>, |
327 |
| -) -> InterpResult<'tcx, ()> { |
328 |
| - let (op, op_len) = this.operand_to_simd(op)?; |
329 |
| - let (dest, dest_len) = this.place_to_simd(dest)?; |
330 |
| - |
331 |
| - assert_eq!(dest_len, op_len); |
332 |
| - |
333 |
| - for i in 0..dest_len { |
334 |
| - let op = this.read_immediate(&this.project_index(&op, i)?)?; |
335 |
| - let dest = this.project_index(&dest, i)?; |
336 |
| - |
337 |
| - let res = unary_op_f32(this, which, &op)?; |
338 |
| - this.write_scalar(res, &dest)?; |
339 |
| - } |
340 |
| - |
341 |
| - Ok(()) |
342 |
| -} |
0 commit comments