diff --git a/rust-version b/rust-version index ba41809f0749..cab2da408db4 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -6a705566166debf5eff88c57140df607fa409aaa +f0c4da49983aa699f715caf681e3154b445fb60b diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index 74914963f74c..e84923314186 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -386,6 +386,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_bool(res), dest)?; } + "simd_select" => { + let &[ref mask, ref yes, ref no] = check_arg_count(args)?; + let (mask, mask_len) = this.operand_to_simd(mask)?; + let (yes, yes_len) = this.operand_to_simd(yes)?; + let (no, no_len) = this.operand_to_simd(no)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, mask_len); + assert_eq!(dest_len, yes_len); + assert_eq!(dest_len, no_len); + + for i in 0..dest_len { + let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?; + let yes = this.read_immediate(&this.mplace_index(&yes, i)?.into())?; + let no = this.read_immediate(&this.mplace_index(&no, i)?.into())?; + let dest = this.mplace_index(&dest, i)?; + + let mask = simd_element_to_bool(mask)?; + let val = if mask { yes } else { no }; + this.write_immediate(*val, &dest.into())?; + } + } // Atomic operations "atomic_load" => this.atomic_load(args, dest, AtomicReadOp::SeqCst)?, diff --git a/tests/run-pass/portable-simd.rs b/tests/run-pass/portable-simd.rs index 17fea5916675..3c1437f0e0fc 100644 --- a/tests/run-pass/portable-simd.rs +++ b/tests/run-pass/portable-simd.rs @@ -29,19 +29,22 @@ fn simd_ops_i32() { fn simd_intrinsics() { extern "platform-intrinsic" { - pub(crate) fn simd_eq(x: T, y: T) -> U; - pub(crate) fn simd_reduce_any(x: T) -> bool; + fn simd_eq(x: T, y: T) -> U; + fn simd_reduce_any(x: T) -> bool; + fn simd_select(m: M, yes: T, no: T) -> T; } - - // Make sure simd_eq returns all-1 for `true` - let a = i32x4::splat(10); - let b = i32x4::from_array([1, 2, 10, 4]); - let c: i32x4 = unsafe { simd_eq(a, b) }; - assert_eq!(c, i32x4::from_array([0, 0, -1, 0])); - unsafe { + // Make sure simd_eq returns all-1 for `true` + let a = i32x4::splat(10); + let b = i32x4::from_array([1, 2, 10, 4]); + let c: i32x4 = simd_eq(a, b); + assert_eq!(c, i32x4::from_array([0, 0, -1, 0])); + assert!(!simd_reduce_any(i32x4::splat(0))); assert!(simd_reduce_any(i32x4::splat(-1))); + + assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), a, b), i32x4::from_array([1, 10, 10, 4])); + assert_eq!(simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10])); } }