From 2d67e40fa83d37dc2afb44cdff1be03a0d064684 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Wed, 8 May 2019 13:56:24 +0000 Subject: [PATCH] Add Altivec vec_splats --- .../crates/core_arch/src/powerpc/altivec.rs | 163 +++++++++++++++--- 1 file changed, 135 insertions(+), 28 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index e73c2e889fa4..9cb37f3cd569 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -163,6 +163,32 @@ extern "C" { fn vminuw(a: vector_unsigned_int, b: vector_unsigned_int) -> vector_unsigned_int; } +macro_rules! s_t_l { + (i32x4) => { + vector_signed_int + }; + (i16x8) => { + vector_signed_short + }; + (i8x16) => { + vector_signed_char + }; + + (u32x4) => { + vector_unsigned_int + }; + (u16x8) => { + vector_unsigned_short + }; + (u8x16) => { + vector_unsigned_char + }; + + (f32x4) => { + vector_float + }; +} + mod sealed { use super::*; @@ -174,10 +200,39 @@ mod sealed { unsafe fn $fun ($($v : $ty),*) -> $r { $call ($($v),*) } + }; + ($fun:ident ($($v:ident : $ty:ty),*) -> $r:ty [$call:ident, $instr_altivec:ident / $instr_vsx:ident]) => { + #[inline] + #[target_feature(enable = "altivec")] + #[cfg_attr(all(test, not(target_feature="vsx")), assert_instr($instr_altivec))] + #[cfg_attr(all(test, target_feature="vsx"), assert_instr($instr_vsx))] + unsafe fn $fun ($($v : $ty),*) -> $r { + $call ($($v),*) + } } + } macro_rules! impl_vec_trait { + ([$Trait:ident $m:ident] $fun:ident ($a:ty) -> $r:ty) => { + impl $Trait for $a { + type Result = $r; + #[inline] + #[target_feature(enable = "altivec")] + unsafe fn $m(self) -> Self::Result { + $fun(transmute(self)) + } + } + }; + ([$Trait:ident $m:ident] ($ub:ident, $sb:ident, $uh:ident, $sh:ident, $uw:ident, $sw:ident, $sf: ident)) => { + impl_vec_trait!{ [$Trait $m] $ub (vector_unsigned_char) -> vector_unsigned_char } + impl_vec_trait!{ [$Trait $m] $sb (vector_signed_char) -> vector_signed_char } + impl_vec_trait!{ [$Trait $m] $uh (vector_unsigned_short) -> vector_unsigned_short } + impl_vec_trait!{ [$Trait $m] $sh (vector_signed_short) -> vector_signed_short } + impl_vec_trait!{ [$Trait $m] $uw (vector_unsigned_int) -> vector_unsigned_int } + impl_vec_trait!{ [$Trait $m] $sw (vector_signed_int) -> vector_signed_int } + impl_vec_trait!{ [$Trait $m] $sf (vector_float) -> vector_float } + }; ([$Trait:ident $m:ident] $fun:ident ($a:ty, $b:ty) -> $r:ty) => { impl $Trait<$b> for $a { type Result = $r; @@ -193,7 +248,7 @@ mod sealed { impl_vec_trait!{ [$Trait $m] $fun ($a, $b) -> $r } impl_vec_trait!{ [$Trait $m] $fun ($b, $a) -> $r } }; - ([$Trait:ident $m:ident] ($ub:ident, $sb:ident, $uh:ident, $sh:ident, $uw:ident, $sw:ident)) => { + ([$Trait:ident $m:ident] ~($ub:ident, $sb:ident, $uh:ident, $sh:ident, $uw:ident, $sw:ident)) => { impl_vec_trait!{ [$Trait $m] $ub (vector_unsigned_char, ~vector_bool_char) -> vector_unsigned_char } impl_vec_trait!{ [$Trait $m] $sb (vector_signed_char, ~vector_bool_char) -> vector_signed_char } impl_vec_trait!{ [$Trait $m] $uh (vector_unsigned_short, ~vector_bool_short) -> vector_unsigned_short } @@ -203,6 +258,55 @@ mod sealed { } } + macro_rules! splats { + ($name:ident, $v:ident, $r:ident) => { + #[inline] + #[target_feature(enable = "altivec")] + unsafe fn $name(v: $v) -> s_t_l!($r) { + transmute($r::splat(v)) + } + }; + } + + splats! { splats_u8, u8, u8x16 } + splats! { splats_u16, u16, u16x8 } + splats! { splats_u32, u32, u32x4 } + splats! { splats_i8, i8, i8x16 } + splats! { splats_i16, i16, i16x8 } + splats! { splats_i32, i32, i32x4 } + splats! { splats_f32, f32, f32x4 } + + test_impl! { vec_splats_u8 (v: u8) -> vector_unsigned_char [splats_u8, vspltb] } + test_impl! { vec_splats_u16 (v: u16) -> vector_unsigned_short [splats_u16, vsplth] } + test_impl! { vec_splats_u32 (v: u32) -> vector_unsigned_int [splats_u32, vspltw / xxspltw] } + test_impl! { vec_splats_i8 (v: i8) -> vector_signed_char [splats_i8, vspltb] } + test_impl! { vec_splats_i16 (v: i16) -> vector_signed_short [splats_i16, vsplth] } + test_impl! { vec_splats_i32 (v: i32) -> vector_signed_int [splats_i32, vspltw / xxspltw] } + test_impl! { vec_splats_f32 (v: f32) -> vector_float [splats_f32, vspltw / xxspltw] } + + pub trait VectorSplats { + type Result; + unsafe fn vec_splats(self) -> Self::Result; + } + + macro_rules! impl_vec_splats { + ($(($fn:ident ($ty:ty) -> $r:ty)),*) => { + $( + impl_vec_trait!{ [VectorSplats vec_splats] $fn ($ty) -> $r } + )* + } + } + + impl_vec_splats! { + (vec_splats_u8 (u8) -> vector_unsigned_char), + (vec_splats_i8 (i8) -> vector_signed_char), + (vec_splats_u16 (u16) -> vector_unsigned_short), + (vec_splats_i16 (i16) -> vector_signed_short), + (vec_splats_u32 (u32) -> vector_unsigned_int), + (vec_splats_i32 (i32) -> vector_signed_int), + (vec_splats_f32 (f32) -> vector_float) + } + test_impl! { vec_vsububm (a: vector_unsigned_char, b: vector_unsigned_char) -> vector_unsigned_char [simd_sub, vsububm] } test_impl! { vec_vsubuhm (a: vector_unsigned_short, b: vector_unsigned_short) -> vector_unsigned_short [simd_sub, vsubuhm] } test_impl! { vec_vsubuwm (a: vector_unsigned_int, b: vector_unsigned_int) -> vector_unsigned_int [simd_sub, vsubuwm] } @@ -212,7 +316,7 @@ mod sealed { unsafe fn vec_sub(self, b: Other) -> Self::Result; } - impl_vec_trait! { [VectorSub vec_sub] (simd_sub, simd_sub, simd_sub, simd_sub, simd_sub, simd_sub) } + impl_vec_trait! { [VectorSub vec_sub] ~(simd_sub, simd_sub, simd_sub, simd_sub, simd_sub, simd_sub) } test_impl! { vec_vminsb (a: vector_signed_char, b: vector_signed_char) -> vector_signed_char [vminsb, vminsb] } test_impl! { vec_vminsh (a: vector_signed_short, b: vector_signed_short) -> vector_signed_short [vminsh, vminsh] } @@ -227,7 +331,7 @@ mod sealed { unsafe fn vec_min(self, b: Other) -> Self::Result; } - impl_vec_trait! { [VectorMin vec_min] (vminub, vminsb, vminuh, vminsh, vminuw, vminsw) } + impl_vec_trait! { [VectorMin vec_min] ~(vminub, vminsb, vminuh, vminsh, vminuw, vminsw) } test_impl! { vec_vmaxsb (a: vector_signed_char, b: vector_signed_char) -> vector_signed_char [vmaxsb, vmaxsb] } test_impl! { vec_vmaxsh (a: vector_signed_short, b: vector_signed_short) -> vector_signed_short [vmaxsh, vmaxsh] } @@ -242,7 +346,7 @@ mod sealed { unsafe fn vec_max(self, b: Other) -> Self::Result; } - impl_vec_trait! { [VectorMax vec_max] (vmaxub, vmaxsb, vmaxuh, vmaxsh, vmaxuw, vmaxsw) } + impl_vec_trait! { [VectorMax vec_max] ~(vmaxub, vmaxsb, vmaxuh, vmaxsh, vmaxuw, vmaxsw) } #[inline] #[target_feature(enable = "altivec")] @@ -939,6 +1043,16 @@ mod sealed { vector_mladd! { vector_signed_short, vector_signed_short, vector_signed_short } } +/// Vector splats. +#[inline] +#[target_feature(enable = "altivec")] +pub unsafe fn vec_splats(a: T) -> ::Result +where + T: sealed::VectorSplats, +{ + a.vec_splats() +} + /// Vector sub. #[inline] #[target_feature(enable = "altivec")] @@ -1172,32 +1286,25 @@ mod tests { use crate::core_arch::simd::*; use stdsimd_test::simd_test; - macro_rules! s_t_l { - (i32x4) => { - vector_signed_int - }; - (i16x8) => { - vector_signed_short - }; - (i8x16) => { - vector_signed_char - }; - - (u32x4) => { - vector_unsigned_int - }; - (u16x8) => { - vector_unsigned_short - }; - (u8x16) => { - vector_unsigned_char - }; - - (f32x4) => { - vector_float - }; + macro_rules! test_vec_splats { + { $name: ident, $ty: ident, $a: expr } => { + #[simd_test(enable = "altivec")] + unsafe fn $name() { + let a: s_t_l!($ty) = vec_splats($a); + let d = $ty::splat($a); + assert_eq!(d, transmute(a)); + } + } } + test_vec_splats! { test_vec_splats_u8, u8x16, 42u8 } + test_vec_splats! { test_vec_splats_u16, u16x8, 42u16 } + test_vec_splats! { test_vec_splats_u32, u32x4, 42u32 } + test_vec_splats! { test_vec_splats_i8, i8x16, 42i8 } + test_vec_splats! { test_vec_splats_i16, i16x8, 42i16 } + test_vec_splats! { test_vec_splats_i32, i32x4, 42i32 } + test_vec_splats! { test_vec_splats_f32, f32x4, 42f32 } + macro_rules! test_vec_sub { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")]