diff --git a/rust-version b/rust-version index 45cd53ac6c1..e7e504a38a7 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -c9c4b5d7276297679387189d96a952f2b760e7ad +5bc98076f37dd8c1476de4bbe0515c55a65332b7 diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index f2f046a3ada..d684b41ed81 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -305,6 +305,32 @@ fn call_intrinsic( this.write_scalar(res, dest)?; } + // SIMD operations + "simd_add" | "simd_sub" | "simd_mul" | "simd_div" => { + let &[ref left, ref right] = check_arg_count(args)?; + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + let op = match intrinsic_name { + "simd_add" => mir::BinOp::Add, + "simd_sub" => mir::BinOp::Sub, + "simd_mul" => mir::BinOp::Mul, + "simd_div" => mir::BinOp::Div, + _ => unreachable!(), + }; + + for i in 0..dest_len { + let left = this.read_immediate(&this.mplace_index(&left, i)?.into())?; + let right = this.read_immediate(&this.mplace_index(&right, i)?.into())?; + let dest = this.mplace_index(&dest, i)?.into(); + this.binop_ignore_overflow(op, &left, &right, &dest)?; + } + } + // Atomic operations "atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?, "atomic_load_relaxed" => this.atomic_load(args, dest, AtomicReadOp::Relaxed)?, diff --git a/tests/run-pass/portable-simd.rs b/tests/run-pass/portable-simd.rs new file mode 100644 index 00000000000..42a6befd868 --- /dev/null +++ b/tests/run-pass/portable-simd.rs @@ -0,0 +1,27 @@ +#![feature(portable_simd)] +use std::simd::*; + +fn simd_ops_f32() { + let a = f32x4::splat(10.0); + let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]); + assert_eq!(a + b, f32x4::from_array([11.0, 12.0, 13.0, 14.0])); + assert_eq!(a - b, f32x4::from_array([9.0, 8.0, 7.0, 6.0])); + assert_eq!(a * b, f32x4::from_array([10.0, 20.0, 30.0, 40.0])); + assert_eq!(b / a, f32x4::from_array([0.1, 0.2, 0.3, 0.4])); + assert_eq!(a / 2.0, f32x4::splat(5.0)); +} + +fn simd_ops_i32() { + let a = i32x4::splat(10); + let b = i32x4::from_array([1, 2, 3, 4]); + assert_eq!(a + b, i32x4::from_array([11, 12, 13, 14])); + assert_eq!(a - b, i32x4::from_array([9, 8, 7, 6])); + assert_eq!(a * b, i32x4::from_array([10, 20, 30, 40])); + assert_eq!(a / b, i32x4::from_array([10, 5, 3, 2])); + assert_eq!(a / 2, i32x4::splat(5)); +} + +fn main() { + simd_ops_f32(); + simd_ops_i32(); +}