@@ -324,12 +324,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
324
324
325
325
assert_eq ! ( dest_len, op_len) ;
326
326
327
+ enum Op {
328
+ MirOp ( mir:: UnOp ) ,
329
+ Abs ,
330
+ }
331
+ let which = match intrinsic_name {
332
+ "simd_neg" => Op :: MirOp ( mir:: UnOp :: Neg ) ,
333
+ "simd_fabs" => Op :: Abs ,
334
+ _ => unreachable ! ( ) ,
335
+ } ;
336
+
327
337
for i in 0 ..dest_len {
328
338
let op = this. read_immediate ( & this. mplace_index ( & op, i) ?. into ( ) ) ?;
329
339
let dest = this. mplace_index ( & dest, i) ?;
330
- let val = match intrinsic_name {
331
- "simd_neg" => this. unary_op ( mir :: UnOp :: Neg , & op) ?. to_scalar ( ) ?,
332
- "simd_fabs" => {
340
+ let val = match which {
341
+ Op :: MirOp ( mir_op ) => this. unary_op ( mir_op , & op) ?. to_scalar ( ) ?,
342
+ Op :: Abs => {
333
343
// Works for f32 and f64.
334
344
let ty:: Float ( float_ty) = op. layout . ty . kind ( ) else {
335
345
bug ! ( "simd_fabs operand is not a float" )
@@ -341,7 +351,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
341
351
FloatTy :: F64 => Scalar :: from_f64 ( op. to_f64 ( ) ?. abs ( ) ) ,
342
352
}
343
353
}
344
- _ => bug ! ( ) ,
345
354
} ;
346
355
this. write_scalar ( val, & dest. into ( ) ) ?;
347
356
}
@@ -419,28 +428,49 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
419
428
}
420
429
}
421
430
}
422
- "simd_reduce_any" | "simd_reduce_all" => {
431
+ #[ rustfmt:: skip]
432
+ | "simd_reduce_and"
433
+ | "simd_reduce_or"
434
+ | "simd_reduce_xor"
435
+ | "simd_reduce_any"
436
+ | "simd_reduce_all" => {
437
+ use mir:: BinOp ;
438
+
423
439
let & [ ref op] = check_arg_count ( args) ?;
424
440
let ( op, op_len) = this. operand_to_simd ( op) ?;
425
441
426
- // the neutral element
427
- let mut res = match intrinsic_name {
428
- "simd_reduce_any" => false ,
429
- "simd_reduce_all" => true ,
430
- _ => bug ! ( ) ,
442
+ let imm_from_bool =
443
+ |b| ImmTy :: from_scalar ( Scalar :: from_bool ( b) , this. machine . layouts . bool ) ;
444
+
445
+ enum Op {
446
+ MirOp ( BinOp ) ,
447
+ MirOpBool ( BinOp ) ,
448
+ }
449
+ // The initial value is the neutral element.
450
+ let ( which, init) = match intrinsic_name {
451
+ "simd_reduce_and" => ( Op :: MirOp ( BinOp :: BitAnd ) , ImmTy :: from_int ( -1 , dest. layout ) ) ,
452
+ "simd_reduce_or" => ( Op :: MirOp ( BinOp :: BitOr ) , ImmTy :: from_int ( 0 , dest. layout ) ) ,
453
+ "simd_reduce_xor" => ( Op :: MirOp ( BinOp :: BitXor ) , ImmTy :: from_int ( 0 , dest. layout ) ) ,
454
+ "simd_reduce_any" => ( Op :: MirOpBool ( BinOp :: BitOr ) , imm_from_bool ( false ) ) ,
455
+ "simd_reduce_all" => ( Op :: MirOpBool ( BinOp :: BitAnd ) , imm_from_bool ( true ) ) ,
456
+ _ => unreachable ! ( ) ,
431
457
} ;
432
458
459
+ let mut res = init;
433
460
for i in 0 ..op_len {
434
461
let op = this. read_immediate ( & this. mplace_index ( & op, i) ?. into ( ) ) ?;
435
- let val = simd_element_to_bool ( op) ?;
436
- res = match intrinsic_name {
437
- "simd_reduce_any" => res | val,
438
- "simd_reduce_all" => res & val,
439
- _ => bug ! ( ) ,
462
+ res = match which {
463
+ Op :: MirOp ( mir_op) => {
464
+ this. binary_op ( mir_op, & res, & op) ?
465
+ }
466
+ Op :: MirOpBool ( mir_op) => {
467
+ let op = imm_from_bool ( simd_element_to_bool ( op) ?) ;
468
+ this. binary_op ( mir_op, & res, & op) ?
469
+ }
440
470
} ;
441
471
}
442
472
443
- this. write_scalar ( Scalar :: from_bool ( res) , dest) ?;
473
+ this. write_immediate ( * res, dest) ?;
444
474
}
445
475
"simd_select" => {
446
476
let & [ ref mask, ref yes, ref no] = check_arg_count ( args) ?;
0 commit comments