| //! Vertical (lane-wise) vector-vector shifts operations. |
| |
| macro_rules! impl_ops_vector_shifts { |
| ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => { |
| impl crate::ops::Shl<$id> for $id { |
| type Output = Self; |
| #[inline] |
| fn shl(self, other: Self) -> Self { |
| use crate::llvm::simd_shl; |
| unsafe { Simd(simd_shl(self.0, other.0)) } |
| } |
| } |
| impl crate::ops::Shr<$id> for $id { |
| type Output = Self; |
| #[inline] |
| fn shr(self, other: Self) -> Self { |
| use crate::llvm::simd_shr; |
| unsafe { Simd(simd_shr(self.0, other.0)) } |
| } |
| } |
| impl crate::ops::ShlAssign<$id> for $id { |
| #[inline] |
| fn shl_assign(&mut self, other: Self) { |
| *self = *self << other; |
| } |
| } |
| impl crate::ops::ShrAssign<$id> for $id { |
| #[inline] |
| fn shr_assign(&mut self, other: Self) { |
| *self = *self >> other; |
| } |
| } |
| test_if!{ |
| $test_tt: |
| paste::item! { |
| pub mod [<$id _ops_vector_shifts>] { |
| use super::*; |
| #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] |
| #[cfg_attr(any(target_arch = "s390x", target_arch = "sparc64"), |
| allow(unreachable_code, unused_variables, unused_mut))] |
| // ^^^ FIXME: https://github.com/rust-lang/rust/issues/55344 |
| fn ops_vector_shifts() { |
| let z = $id::splat(0 as $elem_ty); |
| let o = $id::splat(1 as $elem_ty); |
| let t = $id::splat(2 as $elem_ty); |
| let f = $id::splat(4 as $elem_ty); |
| |
| let max = |
| $id::splat((mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty); |
| |
| // shr |
| assert_eq!(z >> z, z); |
| assert_eq!(z >> o, z); |
| assert_eq!(z >> t, z); |
| assert_eq!(z >> t, z); |
| |
| #[cfg(any(target_arch = "s390x", target_arch = "sparc64"))] { |
| // FIXME: rust produces bad codegen for shifts: |
| // https://github.com/rust-lang-nursery/packed_simd/issues/13 |
| return; |
| } |
| |
| assert_eq!(o >> z, o); |
| assert_eq!(t >> z, t); |
| assert_eq!(f >> z, f); |
| assert_eq!(f >> max, z); |
| |
| assert_eq!(o >> o, z); |
| assert_eq!(t >> o, o); |
| assert_eq!(t >> t, z); |
| assert_eq!(f >> o, t); |
| assert_eq!(f >> t, o); |
| assert_eq!(f >> max, z); |
| |
| // shl |
| assert_eq!(z << z, z); |
| assert_eq!(o << z, o); |
| assert_eq!(t << z, t); |
| assert_eq!(f << z, f); |
| assert_eq!(f << max, z); |
| |
| assert_eq!(o << o, t); |
| assert_eq!(o << t, f); |
| assert_eq!(t << o, f); |
| |
| { |
| // shr_assign |
| let mut v = o; |
| v >>= o; |
| assert_eq!(v, z); |
| } |
| { |
| // shl_assign |
| let mut v = o; |
| v <<= o; |
| assert_eq!(v, t); |
| } |
| } |
| } |
| } |
| } |
| }; |
| } |