@@ -433,7 +433,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
433
433
| "simd_reduce_or"
434
434
| "simd_reduce_xor"
435
435
| "simd_reduce_any"
436
- | "simd_reduce_all" => {
436
+ | "simd_reduce_all"
437
+ | "simd_reduce_max"
438
+ | "simd_reduce_min" => {
437
439
use mir:: BinOp ;
438
440
439
441
let & [ ref op] = check_arg_count ( args) ?;
@@ -445,19 +447,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
445
447
enum Op {
446
448
MirOp ( BinOp ) ,
447
449
MirOpBool ( BinOp ) ,
450
+ Max ,
451
+ Min ,
448
452
}
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 ) ) ,
453
+ let which = match intrinsic_name {
454
+ "simd_reduce_and" => Op :: MirOp ( BinOp :: BitAnd ) ,
455
+ "simd_reduce_or" => Op :: MirOp ( BinOp :: BitOr ) ,
456
+ "simd_reduce_xor" => Op :: MirOp ( BinOp :: BitXor ) ,
457
+ "simd_reduce_any" => Op :: MirOpBool ( BinOp :: BitOr ) ,
458
+ "simd_reduce_all" => Op :: MirOpBool ( BinOp :: BitAnd ) ,
459
+ "simd_reduce_max" => Op :: Max ,
460
+ "simd_reduce_min" => Op :: Min ,
456
461
_ => unreachable ! ( ) ,
457
462
} ;
458
463
459
- let mut res = init;
460
- for i in 0 ..op_len {
464
+ // Initialize with first lane, then proceed with the rest.
465
+ let mut res = this. read_immediate ( & this. mplace_index ( & op, 0 ) ?. into ( ) ) ?;
466
+ if matches ! ( which, Op :: MirOpBool ( _) ) {
467
+ // Convert to `bool` scalar.
468
+ res = imm_from_bool ( simd_element_to_bool ( res) ?) ;
469
+ }
470
+ for i in 1 ..op_len {
461
471
let op = this. read_immediate ( & this. mplace_index ( & op, i) ?. into ( ) ) ?;
462
472
res = match which {
463
473
Op :: MirOp ( mir_op) => {
@@ -467,6 +477,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
467
477
let op = imm_from_bool ( simd_element_to_bool ( op) ?) ;
468
478
this. binary_op ( mir_op, & res, & op) ?
469
479
}
480
+ Op :: Max => {
481
+ // if `op > res`...
482
+ if this. binary_op ( BinOp :: Gt , & op, & res) ?. to_scalar ( ) ?. to_bool ( ) ? {
483
+ // update accumulator
484
+ op
485
+ } else {
486
+ // no change
487
+ res
488
+ }
489
+ }
490
+ Op :: Min => {
491
+ // if `op < res`...
492
+ if this. binary_op ( BinOp :: Lt , & op, & res) ?. to_scalar ( ) ?. to_bool ( ) ? {
493
+ // update accumulator
494
+ op
495
+ } else {
496
+ // no change
497
+ res
498
+ }
499
+ }
470
500
} ;
471
501
}
472
502
this. write_immediate ( * res, dest) ?;
0 commit comments