@@ -329,7 +329,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
329
329
| "simd_ceil"
330
330
| "simd_floor"
331
331
| "simd_round"
332
- | "simd_trunc" => {
332
+ | "simd_trunc"
333
+ | "simd_fsqrt" => {
333
334
let & [ ref op] = check_arg_count ( args) ?;
334
335
let ( op, op_len) = this. operand_to_simd ( op) ?;
335
336
let ( dest, dest_len) = this. place_to_simd ( dest) ?;
@@ -342,6 +343,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
342
343
Floor ,
343
344
Round ,
344
345
Trunc ,
346
+ Sqrt ,
345
347
}
346
348
#[ derive( Copy , Clone ) ]
347
349
enum Op {
@@ -356,6 +358,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
356
358
"simd_floor" => Op :: HostOp ( HostFloatOp :: Floor ) ,
357
359
"simd_round" => Op :: HostOp ( HostFloatOp :: Round ) ,
358
360
"simd_trunc" => Op :: HostOp ( HostFloatOp :: Trunc ) ,
361
+ "simd_fsqrt" => Op :: HostOp ( HostFloatOp :: Sqrt ) ,
359
362
_ => unreachable ! ( ) ,
360
363
} ;
361
364
@@ -388,6 +391,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
388
391
HostFloatOp :: Floor => f. floor ( ) ,
389
392
HostFloatOp :: Round => f. round ( ) ,
390
393
HostFloatOp :: Trunc => f. trunc ( ) ,
394
+ HostFloatOp :: Sqrt => f. sqrt ( ) ,
391
395
} ;
392
396
Scalar :: from_u32 ( res. to_bits ( ) )
393
397
}
@@ -398,6 +402,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
398
402
HostFloatOp :: Floor => f. floor ( ) ,
399
403
HostFloatOp :: Round => f. round ( ) ,
400
404
HostFloatOp :: Trunc => f. trunc ( ) ,
405
+ HostFloatOp :: Sqrt => f. sqrt ( ) ,
401
406
} ;
402
407
Scalar :: from_u64 ( res. to_bits ( ) )
403
408
}
@@ -508,6 +513,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
508
513
this. write_scalar ( val, & dest. into ( ) ) ?;
509
514
}
510
515
}
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
+ }
511
546
#[ rustfmt:: skip]
512
547
| "simd_reduce_and"
513
548
| "simd_reduce_or"
0 commit comments