@@ -329,7 +329,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
329329 | "simd_ceil"
330330 | "simd_floor"
331331 | "simd_round"
332- | "simd_trunc" => {
332+ | "simd_trunc"
333+ | "simd_fsqrt" => {
333334 let & [ ref op] = check_arg_count ( args) ?;
334335 let ( op, op_len) = this. operand_to_simd ( op) ?;
335336 let ( dest, dest_len) = this. place_to_simd ( dest) ?;
@@ -342,6 +343,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
342343 Floor ,
343344 Round ,
344345 Trunc ,
346+ Sqrt ,
345347 }
346348 #[ derive( Copy , Clone ) ]
347349 enum Op {
@@ -356,6 +358,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
356358 "simd_floor" => Op :: HostOp ( HostFloatOp :: Floor ) ,
357359 "simd_round" => Op :: HostOp ( HostFloatOp :: Round ) ,
358360 "simd_trunc" => Op :: HostOp ( HostFloatOp :: Trunc ) ,
361+ "simd_fsqrt" => Op :: HostOp ( HostFloatOp :: Sqrt ) ,
359362 _ => unreachable ! ( ) ,
360363 } ;
361364
@@ -388,6 +391,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
388391 HostFloatOp :: Floor => f. floor ( ) ,
389392 HostFloatOp :: Round => f. round ( ) ,
390393 HostFloatOp :: Trunc => f. trunc ( ) ,
394+ HostFloatOp :: Sqrt => f. sqrt ( ) ,
391395 } ;
392396 Scalar :: from_u32 ( res. to_bits ( ) )
393397 }
@@ -398,6 +402,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
398402 HostFloatOp :: Floor => f. floor ( ) ,
399403 HostFloatOp :: Round => f. round ( ) ,
400404 HostFloatOp :: Trunc => f. trunc ( ) ,
405+ HostFloatOp :: Sqrt => f. sqrt ( ) ,
401406 } ;
402407 Scalar :: from_u64 ( res. to_bits ( ) )
403408 }
@@ -508,6 +513,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
508513 this. write_scalar ( val, & dest. into ( ) ) ?;
509514 }
510515 }
516+ "simd_fma" => {
517+ let & [ ref a, ref b, ref c] = check_arg_count ( args) ?;
518+ let ( a, a_len) = this. operand_to_simd ( a) ?;
519+ let ( b, b_len) = this. operand_to_simd ( b) ?;
520+ let ( c, c_len) = this. operand_to_simd ( c) ?;
521+ let ( dest, dest_len) = this. place_to_simd ( dest) ?;
522+
523+ assert_eq ! ( dest_len, a_len) ;
524+ assert_eq ! ( dest_len, b_len) ;
525+ assert_eq ! ( dest_len, c_len) ;
526+
527+ for i in 0 ..dest_len {
528+ let a = this. read_immediate ( & this. mplace_index ( & a, i) ?. into ( ) ) ?. to_scalar ( ) ?;
529+ let b = this. read_immediate ( & this. mplace_index ( & b, i) ?. into ( ) ) ?. to_scalar ( ) ?;
530+ let c = this. read_immediate ( & this. mplace_index ( & c, i) ?. into ( ) ) ?. to_scalar ( ) ?;
531+ let dest = this. mplace_index ( & dest, i) ?;
532+
533+ // Works for f32 and f64.
534+ let ty:: Float ( float_ty) = dest. layout . ty . kind ( ) else {
535+ bug ! ( "{} operand is not a float" , intrinsic_name)
536+ } ;
537+ let val = match float_ty {
538+ FloatTy :: F32 =>
539+ Scalar :: from_f32 ( a. to_f32 ( ) ?. mul_add ( b. to_f32 ( ) ?, c. to_f32 ( ) ?) . value ) ,
540+ FloatTy :: F64 =>
541+ Scalar :: from_f64 ( a. to_f64 ( ) ?. mul_add ( b. to_f64 ( ) ?, c. to_f64 ( ) ?) . value ) ,
542+ } ;
543+ this. write_scalar ( val, & dest. into ( ) ) ?;
544+ }
545+ }
511546 #[ rustfmt:: skip]
512547 | "simd_reduce_and"
513548 | "simd_reduce_or"
0 commit comments