Skip to content

Commit b491b72

Browse files
committed
implement simd_reduce_{add,mul}
1 parent 3ed8ad4 commit b491b72

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

src/shims/intrinsics.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
382382
assert_eq!(dest_len, left_len);
383383
assert_eq!(dest_len, right_len);
384384

385-
let op = match intrinsic_name {
385+
let mir_op = match intrinsic_name {
386386
"simd_add" => BinOp::Add,
387387
"simd_sub" => BinOp::Sub,
388388
"simd_mul" => BinOp::Mul,
@@ -406,16 +406,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
406406
let left = this.read_immediate(&this.mplace_index(&left, i)?.into())?;
407407
let right = this.read_immediate(&this.mplace_index(&right, i)?.into())?;
408408
let dest = this.mplace_index(&dest, i)?;
409-
let (val, overflowed, ty) = this.overflowing_binary_op(op, &left, &right)?;
410-
if matches!(op, BinOp::Shl | BinOp::Shr) {
409+
let (val, overflowed, ty) = this.overflowing_binary_op(mir_op, &left, &right)?;
410+
if matches!(mir_op, BinOp::Shl | BinOp::Shr) {
411411
// Shifts have extra UB as SIMD operations that the MIR binop does not have.
412412
// See <https://github.com/rust-lang/rust/issues/91237>.
413413
if overflowed {
414414
let r_val = right.to_scalar()?.to_bits(right.layout.size)?;
415415
throw_ub_format!("overflowing shift by {} in `{}` in SIMD lane {}", r_val, intrinsic_name, i);
416416
}
417417
}
418-
if matches!(op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) {
418+
if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) {
419419
// Special handling for boolean-returning operations
420420
assert_eq!(ty, this.tcx.types.bool);
421421
let val = val.to_bool().unwrap();
@@ -469,7 +469,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
469469
}
470470
};
471471
}
472+
this.write_immediate(*res, dest)?;
473+
}
474+
#[rustfmt::skip]
475+
| "simd_reduce_add_ordered"
476+
| "simd_reduce_mul_ordered" => {
477+
use mir::BinOp;
478+
479+
let &[ref op, ref init] = check_arg_count(args)?;
480+
let (op, op_len) = this.operand_to_simd(op)?;
481+
let init = this.read_immediate(init)?;
472482

483+
let mir_op = match intrinsic_name {
484+
"simd_reduce_add_ordered" => BinOp::Add,
485+
"simd_reduce_mul_ordered" => BinOp::Mul,
486+
_ => unreachable!(),
487+
};
488+
489+
let mut res = init;
490+
for i in 0..op_len {
491+
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
492+
res = this.binary_op(mir_op, &res, &op)?;
493+
}
473494
this.write_immediate(*res, dest)?;
474495
}
475496
"simd_select" => {

tests/run-pass/portable-simd.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ fn simd_ops_i32() {
7575
assert_eq!(b.horizontal_or(), -1);
7676
assert_eq!(a.horizontal_xor(), 0);
7777
assert_eq!(b.horizontal_xor(), -4);
78+
assert_eq!(a.horizontal_sum(), 40);
79+
assert_eq!(b.horizontal_sum(), 2);
80+
assert_eq!(a.horizontal_product(), 100*100);
81+
assert_eq!(b.horizontal_product(), 6*-4);
7882
}
7983

8084
fn simd_intrinsics() {

0 commit comments

Comments
 (0)