Skip to content

Commit a715171

Browse files
committed
Auto merge of #1997 - RalfJung:simd, r=RalfJung
implement simd_neg and simd_fabs This lets us run the puny portable-simd smoke test in the core test suite. ;)
2 parents 80c3f42 + 0d4902f commit a715171

File tree

4 files changed

+61
-12
lines changed

4 files changed

+61
-12
lines changed

src/data_race.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
553553
let this = self.eval_context_mut();
554554

555555
let old = this.allow_data_races_mut(|this| this.read_immediate(&place.into()))?;
556-
let lt = this.overflowing_binary_op(mir::BinOp::Lt, &old, &rhs)?.0.to_bool()?;
556+
let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar()?.to_bool()?;
557557

558558
let new_val = if min {
559559
if lt { &old } else { &rhs }
@@ -593,11 +593,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
593593
// Read as immediate for the sake of `binary_op()`
594594
let old = this.allow_data_races_mut(|this| this.read_immediate(&(place.into())))?;
595595
// `binary_op` will bail if either of them is not a scalar.
596-
let eq = this.overflowing_binary_op(mir::BinOp::Eq, &old, expect_old)?.0;
596+
let eq = this.binary_op(mir::BinOp::Eq, &old, expect_old)?;
597597
// If the operation would succeed, but is "weak", fail some portion
598598
// of the time, based on `rate`.
599599
let rate = this.memory.extra.cmpxchg_weak_failure_rate;
600-
let cmpxchg_success = eq.to_bool()?
600+
let cmpxchg_success = eq.to_scalar()?.to_bool()?
601601
&& (!can_fail_spuriously || this.memory.extra.rng.get_mut().gen::<f64>() < rate);
602602
let res = Immediate::ScalarPair(
603603
old.to_scalar_or_uninit(),

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(map_try_insert)]
44
#![feature(never_type)]
55
#![feature(try_blocks)]
6+
#![feature(let_else)]
67
#![feature(bool_to_option)]
78
#![warn(rust_2018_idioms)]
89
#![allow(clippy::cast_lossless)]

src/shims/intrinsics.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
316316

317317
// SIMD operations
318318
#[rustfmt::skip]
319+
| "simd_neg"
320+
| "simd_fabs" => {
321+
let &[ref op] = check_arg_count(args)?;
322+
let (op, op_len) = this.operand_to_simd(op)?;
323+
let (dest, dest_len) = this.place_to_simd(dest)?;
324+
325+
assert_eq!(dest_len, op_len);
326+
327+
for i in 0..dest_len {
328+
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
329+
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" => {
333+
// Works for f32 and f64.
334+
let ty::Float(float_ty) = op.layout.ty.kind() else {
335+
bug!("simd_fabs operand is not a float")
336+
};
337+
let op = op.to_scalar()?;
338+
// FIXME: Using host floats.
339+
match float_ty {
340+
FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()),
341+
FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
342+
}
343+
}
344+
_ => bug!(),
345+
};
346+
this.write_scalar(val, &dest.into())?;
347+
}
348+
}
349+
#[rustfmt::skip]
319350
| "simd_add"
320351
| "simd_sub"
321352
| "simd_mul"
@@ -374,12 +405,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
374405
}
375406
}
376407
"simd_reduce_any" => {
377-
let &[ref arg] = check_arg_count(args)?;
378-
let (arg, arg_len) = this.operand_to_simd(arg)?;
408+
let &[ref op] = check_arg_count(args)?;
409+
let (op, op_len) = this.operand_to_simd(op)?;
379410

380411
let mut res = false; // the neutral element
381-
for i in 0..arg_len {
382-
let op = this.read_immediate(&this.mplace_index(&arg, i)?.into())?;
412+
for i in 0..op_len {
413+
let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
383414
let val = simd_element_to_bool(op)?;
384415
res = res | val;
385416
}

tests/run-pass/portable-simd.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,34 @@ use std::simd::*;
33

44
fn simd_ops_f32() {
55
let a = f32x4::splat(10.0);
6-
let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
7-
assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 14.0]));
8-
assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 6.0]));
9-
assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, 40.0]));
10-
assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, 0.4]));
6+
let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
7+
assert_eq!(-b, f32x4::from_array([-1.0, -2.0, -3.0, 4.0]));
8+
assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 6.0]));
9+
assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 14.0]));
10+
assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, -40.0]));
11+
assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, -0.4]));
1112
assert_eq!(a / f32x4::splat(2.0), f32x4::splat(5.0));
1213
assert_eq!(a % b, f32x4::from_array([0.0, 0.0, 1.0, 2.0]));
14+
assert_eq!(b.abs(), f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
15+
}
16+
17+
fn simd_ops_f64() {
18+
let a = f64x4::splat(10.0);
19+
let b = f64x4::from_array([1.0, 2.0, 3.0, -4.0]);
20+
assert_eq!(-b, f64x4::from_array([-1.0, -2.0, -3.0, 4.0]));
21+
assert_eq!(a + b, f64x4::from_array([11.0, 12.0, 13.0, 6.0]));
22+
assert_eq!(a - b, f64x4::from_array([9.0, 8.0, 7.0, 14.0]));
23+
assert_eq!(a * b, f64x4::from_array([10.0, 20.0, 30.0, -40.0]));
24+
assert_eq!(b / a, f64x4::from_array([0.1, 0.2, 0.3, -0.4]));
25+
assert_eq!(a / f64x4::splat(2.0), f64x4::splat(5.0));
26+
assert_eq!(a % b, f64x4::from_array([0.0, 0.0, 1.0, 2.0]));
27+
assert_eq!(b.abs(), f64x4::from_array([1.0, 2.0, 3.0, 4.0]));
1328
}
1429

1530
fn simd_ops_i32() {
1631
let a = i32x4::splat(10);
1732
let b = i32x4::from_array([1, 2, 3, 4]);
33+
assert_eq!(-b, i32x4::from_array([-1, -2, -3, -4]));
1834
assert_eq!(a + b, i32x4::from_array([11, 12, 13, 14]));
1935
assert_eq!(a - b, i32x4::from_array([9, 8, 7, 6]));
2036
assert_eq!(a * b, i32x4::from_array([10, 20, 30, 40]));
@@ -52,6 +68,7 @@ fn simd_intrinsics() {
5268

5369
fn main() {
5470
simd_ops_f32();
71+
simd_ops_f64();
5572
simd_ops_i32();
5673
simd_intrinsics();
5774
}

0 commit comments

Comments
 (0)