diff --git a/crates/core_arch/src/s390x/vector.rs b/crates/core_arch/src/s390x/vector.rs index 1a385fbcec..1e4549da53 100644 --- a/crates/core_arch/src/s390x/vector.rs +++ b/crates/core_arch/src/s390x/vector.rs @@ -3809,6 +3809,186 @@ mod sealed { vector_bool_int vector_unsigned_int vfeef vfenef vfeezf vfenezf vfeefs vfenefs vfeezfs vfenezfs vector_unsigned_int vector_unsigned_int vfeef vfenef vfeezf vfenezf vfeefs vfenefs vfeezfs vfenezfs } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorExtract { + type ElementType; + + unsafe fn vec_extract(a: Self, b: i32) -> Self::ElementType; + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlgvb))] + unsafe fn vlgvb(a: vector_unsigned_char, b: i32) -> u8 { + simd_extract_dyn(a, b as u32 % 16) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlgvh))] + unsafe fn vlgvh(a: vector_unsigned_short, b: i32) -> u16 { + simd_extract_dyn(a, b as u32 % 8) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlgvf))] + unsafe fn vlgvf(a: vector_unsigned_int, b: i32) -> u32 { + simd_extract_dyn(a, b as u32 % 4) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlgvg))] + unsafe fn vlgvg(a: vector_unsigned_long_long, b: i32) -> u64 { + simd_extract_dyn(a, b as u32 % 2) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorInsert { + type ElementType; + + unsafe fn vec_insert(a: Self::ElementType, b: Self, c: i32) -> Self; + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorPromote: Sized { + type ElementType; + + unsafe fn vec_promote(a: Self::ElementType, b: i32) -> MaybeUninit; + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlvgb))] + unsafe fn vlvgb(a: u8, b: vector_unsigned_char, c: i32) -> vector_unsigned_char { + simd_insert_dyn(b, c as u32 % 16, a) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlvgh))] + unsafe fn vlvgh(a: u16, b: vector_unsigned_short, c: i32) -> vector_unsigned_short { + simd_insert_dyn(b, c as u32 % 8, a) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlvgf))] + unsafe fn vlvgf(a: u32, b: vector_unsigned_int, c: i32) -> vector_unsigned_int { + simd_insert_dyn(b, c as u32 % 4, a) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vlvgg))] + unsafe fn vlvgg(a: u64, b: vector_unsigned_long_long, c: i32) -> vector_unsigned_long_long { + simd_insert_dyn(b, c as u32 % 2, a) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorInsertAndZero { + type ElementType; + + unsafe fn vec_insert_and_zero(a: *const Self::ElementType) -> Self; + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vllezb))] + unsafe fn vllezb(x: *const u8) -> vector_unsigned_char { + vector_unsigned_char([0, 0, 0, 0, 0, 0, 0, *x, 0, 0, 0, 0, 0, 0, 0, 0]) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vllezh))] + unsafe fn vllezh(x: *const u16) -> vector_unsigned_short { + vector_unsigned_short([0, 0, 0, *x, 0, 0, 0, 0]) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vllezf))] + unsafe fn vllezf(x: *const u32) -> vector_unsigned_int { + vector_unsigned_int([0, *x, 0, 0]) + } + + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr(vllezg))] + unsafe fn vllezg(x: *const u64) -> vector_unsigned_long_long { + vector_unsigned_long_long([*x, 0]) + } + + macro_rules! impl_extract_insert { + ($($ty:ident $extract_intr:ident $insert_intr:ident $insert_and_zero_intr:ident)*) => { + $( + #[unstable(feature = "stdarch_s390x", issue = "135681")] + impl VectorExtract for $ty { + type ElementType = l_t_t!($ty); + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_extract(a: Self, b: i32) -> Self::ElementType { + transmute($extract_intr(transmute(a), b)) + } + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + impl VectorInsert for $ty { + type ElementType = l_t_t!($ty); + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_insert(a: Self::ElementType, b: Self, c: i32) -> Self { + transmute($insert_intr(transmute(a), transmute(b), c)) + } + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + impl VectorInsertAndZero for $ty { + type ElementType = l_t_t!($ty); + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_insert_and_zero(a: *const Self::ElementType) -> Self { + transmute($insert_and_zero_intr(a.cast())) + } + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + impl VectorPromote for $ty { + type ElementType = l_t_t!($ty); + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_promote(a: Self::ElementType, c: i32) -> MaybeUninit { + // Rust does not currently support `MaybeUninit` element types to simd + // vectors. In C/LLVM that is allowed (using poison values). So rust will + // use an extra instruction to zero the memory. + let b = MaybeUninit::<$ty>::zeroed(); + MaybeUninit::new(transmute($insert_intr(transmute(a), transmute(b), c))) + } + } + )* + } + + } + + impl_extract_insert! { + vector_signed_char vlgvb vlvgb vllezb + vector_unsigned_char vlgvb vlvgb vllezb + vector_signed_short vlgvh vlvgh vllezh + vector_unsigned_short vlgvh vlvgh vllezh + vector_signed_int vlgvf vlvgf vllezf + vector_unsigned_int vlgvf vlvgf vllezf + vector_signed_long_long vlgvg vlvgg vllezg + vector_unsigned_long_long vlgvg vlvgg vllezg + vector_float vlgvf vlvgf vllezf + vector_double vlgvg vlvgg vllezg + } } /// Load Count to Block Boundary @@ -5646,6 +5826,38 @@ pub unsafe fn vec_any_nge(a: T, b: T) -> i32 { vec_any_lt(a, b) } +/// Vector Extract +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_extract(a: T, b: i32) -> T::ElementType { + T::vec_extract(a, b) +} + +/// Vector Insert +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_insert(a: T::ElementType, b: T, c: i32) -> T { + T::vec_insert(a, b, c) +} + +/// Vector Insert and Zero +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_insert_and_zero(a: *const T::ElementType) -> T { + T::vec_insert_and_zero(a) +} + +/// Vector Promote +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_promote(a: T::ElementType, b: i32) -> MaybeUninit { + T::vec_promote(a, b) +} + #[cfg(test)] mod tests { use super::*; @@ -7189,4 +7401,35 @@ mod tests { let d = unsafe { vec_mladd(a, b, c) }; assert_eq!(d.as_array(), &[-3, -10, -19, -30]); } + + #[simd_test(enable = "vector")] + fn test_vec_extract() { + let v = vector_unsigned_int([1, 2, 3, 4]); + + assert_eq!(unsafe { vec_extract(v, 1) }, 2); + assert_eq!(unsafe { vec_extract(v, 4 + 2) }, 3); + } + + #[simd_test(enable = "vector")] + fn test_vec_insert() { + let mut v = vector_unsigned_int([1, 2, 3, 4]); + + v = unsafe { vec_insert(42, v, 1) }; + assert_eq!(v.as_array(), &[1, 42, 3, 4]); + + v = unsafe { vec_insert(64, v, 6) }; + assert_eq!(v.as_array(), &[1, 42, 64, 4]); + } + + #[simd_test(enable = "vector")] + fn test_vec_promote() { + let v: vector_unsigned_int = unsafe { vec_promote(42, 1).assume_init() }; + assert_eq!(v.as_array(), &[0, 42, 0, 0]); + } + + #[simd_test(enable = "vector")] + fn test_vec_insert_and_zero() { + let v = unsafe { vec_insert_and_zero::(&42u32) }; + assert_eq!(v.as_array(), vector_unsigned_int([0, 42, 0, 0]).as_array()); + } }