Skip to content

Commit ccaf720

Browse files
committed
Auto merge of #2007 - RalfJung:simd_saturating, r=RalfJung
implement simd_saturating intrinsics
2 parents 64b086a + 735bee2 commit ccaf720

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
297273c45b205820a4c055082c71677197a40b55
1+
d137c3a7bd3b180317044f8ccb9a8b4b3bb07db3

src/shims/intrinsics.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
372372
| "simd_gt"
373373
| "simd_ge"
374374
| "simd_fmax"
375-
| "simd_fmin" => {
375+
| "simd_fmin"
376+
| "simd_saturating_add"
377+
| "simd_saturating_sub" => {
376378
use mir::BinOp;
377379

378380
let &[ref left, ref right] = check_arg_count(args)?;
@@ -385,6 +387,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
385387

386388
enum Op {
387389
MirOp(BinOp),
390+
SaturatingOp(BinOp),
388391
FMax,
389392
FMin,
390393
}
@@ -407,6 +410,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
407410
"simd_ge" => Op::MirOp(BinOp::Ge),
408411
"simd_fmax" => Op::FMax,
409412
"simd_fmin" => Op::FMin,
413+
"simd_saturating_add" => Op::SaturatingOp(BinOp::Add),
414+
"simd_saturating_sub" => Op::SaturatingOp(BinOp::Sub),
410415
_ => unreachable!(),
411416
};
412417

@@ -442,6 +447,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
442447
Op::FMin => {
443448
fmin_op(&left, &right)?
444449
}
450+
Op::SaturatingOp(mir_op) => {
451+
this.saturating_arith(mir_op, &left, &right)?
452+
}
445453
};
446454
this.write_scalar(val, &dest.into())?;
447455
}

tests/run-pass/portable-simd.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,27 @@ fn simd_ops_i32() {
102102
assert_eq!(a % b, i32x4::from_array([0, 0, 1, 2]));
103103
assert_eq!(i32x2::splat(i32::MIN) % i32x2::splat(-1), i32x2::splat(0));
104104
assert_eq!(b.abs(), i32x4::from_array([1, 2, 3, 4]));
105-
// FIXME not a per-lane method (https://github.com/rust-lang/rust/issues/94682)
105+
// FIXME not a per-lane method (https://github.com/rust-lang/portable-simd/issues/247)
106106
// assert_eq!(a.max(b * i32x4::splat(4)), i32x4::from_array([10, 10, 12, 10]));
107107
// assert_eq!(a.min(b * i32x4::splat(4)), i32x4::from_array([4, 8, 10, -16]));
108108

109+
assert_eq!(
110+
i8x4::from_array([i8::MAX, -23, 23, i8::MIN]).saturating_add(i8x4::from_array([1, i8::MIN, i8::MAX, 28])),
111+
i8x4::from_array([i8::MAX, i8::MIN, i8::MAX, -100])
112+
);
113+
assert_eq!(
114+
i8x4::from_array([i8::MAX, -28, 27, 42]).saturating_sub(i8x4::from_array([1, i8::MAX, i8::MAX, -80])),
115+
i8x4::from_array([126, i8::MIN, -100, 122])
116+
);
117+
assert_eq!(
118+
u8x4::from_array([u8::MAX, 0, 23, 42]).saturating_add(u8x4::from_array([1, 1, u8::MAX, 200])),
119+
u8x4::from_array([u8::MAX, 1, u8::MAX, 242])
120+
);
121+
assert_eq!(
122+
u8x4::from_array([u8::MAX, 0, 23, 42]).saturating_sub(u8x4::from_array([1, 1, u8::MAX, 200])),
123+
u8x4::from_array([254, 0, 0, 0])
124+
);
125+
109126
assert_eq!(!b, i32x4::from_array([!1, !2, !3, !-4]));
110127
assert_eq!(b << i32x4::splat(2), i32x4::from_array([4, 8, 12, -16]));
111128
assert_eq!(b >> i32x4::splat(1), i32x4::from_array([0, 1, 1, -2]));

0 commit comments

Comments
 (0)