From fe6f4d96d86fc01d05cab521b163902165e38849 Mon Sep 17 00:00:00 2001 From: Lei Huang Date: Thu, 18 Jun 2026 12:27:19 -0400 Subject: [PATCH 1/2] PowerPC:Add vec_min/vec_max support for vector float/double Adds floating-point support to the existing vec_min and vec_max intrinsics for PowerPC. --- crates/core_arch/src/powerpc/altivec.rs | 51 +++++++++++-------------- crates/core_arch/src/powerpc/macros.rs | 37 ++++++++++++++++++ crates/core_arch/src/powerpc/vsx.rs | 44 +++++++++++++++++++++ 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/crates/core_arch/src/powerpc/altivec.rs b/crates/core_arch/src/powerpc/altivec.rs index ccfed88a93..5181c4bb39 100644 --- a/crates/core_arch/src/powerpc/altivec.rs +++ b/crates/core_arch/src/powerpc/altivec.rs @@ -230,6 +230,11 @@ unsafe extern "unadjusted" { #[link_name = "llvm.umin.v4i32"] fn vminuw(a: vector_unsigned_int, b: vector_unsigned_int) -> vector_unsigned_int; + #[link_name = "llvm.ppc.altivec.vmaxfp"] + fn vmaxfp(a: vector_float, b: vector_float) -> vector_float; + #[link_name = "llvm.ppc.altivec.vminfp"] + fn vminfp(a: vector_float, b: vector_float) -> vector_float; + #[link_name = "llvm.ppc.altivec.vsubsbs"] fn vsubsbs(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char; #[link_name = "llvm.ppc.altivec.vsubshs"] @@ -411,7 +416,7 @@ unsafe extern "unadjusted" { } #[macro_use] -mod sealed { +pub(crate) mod sealed { use super::*; #[unstable(feature = "stdarch_powerpc", issue = "111145")] @@ -1657,6 +1662,8 @@ mod sealed { test_impl! { vec_vminuh (a: vector_unsigned_short, b: vector_unsigned_short) -> vector_unsigned_short [vminuh, vminuh] } test_impl! { vec_vminuw (a: vector_unsigned_int, b: vector_unsigned_int) -> vector_unsigned_int [vminuw, vminuw] } + test_impl! { vec_vminfp (a: vector_float, b: vector_float) -> vector_float [vminfp, vminfp / xvminsp] } + #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorMin { type Result; @@ -1664,6 +1671,7 @@ mod sealed { } impl_vec_trait! { [VectorMin vec_min] ~(vminub, vminsb, vminuh, vminsh, vminuw, vminsw) } + impl_vec_trait! { [VectorMin vec_min] vec_vminfp(vector_float, vector_float) -> vector_float } 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] } @@ -1673,6 +1681,8 @@ mod sealed { test_impl! { vec_vmaxuh (a: vector_unsigned_short, b: vector_unsigned_short) -> vector_unsigned_short [vmaxuh, vmaxuh] } test_impl! { vec_vmaxuw (a: vector_unsigned_int, b: vector_unsigned_int) -> vector_unsigned_int [vmaxuw, vmaxuw] } + test_impl! { vec_vmaxfp (a: vector_float, b: vector_float) -> vector_float [vmaxfp, vmaxfp / xvmaxsp] } + #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorMax { type Result; @@ -1680,6 +1690,7 @@ mod sealed { } impl_vec_trait! { [VectorMax vec_max] ~(vmaxub, vmaxsb, vmaxuh, vmaxsh, vmaxuw, vmaxsw) } + impl_vec_trait! { [VectorMax vec_max] vec_vmaxfp(vector_float, vector_float) -> vector_float } #[inline] #[target_feature(enable = "altivec")] @@ -4685,7 +4696,7 @@ mod endian { pub use self::endian::*; #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; use std::mem::transmute; @@ -6118,20 +6129,6 @@ mod tests { [2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0], [0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2] } - macro_rules! test_vec_min { - { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { - #[simd_test(enable = "altivec")] - fn $name() { - let a: s_t_l!($ty) = $ty::new($($a),+).into(); - let b: s_t_l!($ty) = $ty::new($($b),+).into(); - - let d = $ty::new($($d),+); - let r = $ty::from(unsafe { vec_min(a, b) }); - assert_eq!(d, r); - } - } - } - test_vec_min! { test_vec_min_i32x4, i32x4, [-1, 0, 1, 2], [2, 1, -1, -2], @@ -6162,19 +6159,10 @@ mod tests { [2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] } - macro_rules! test_vec_max { - { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { - #[simd_test(enable = "altivec")] - fn $name() { - let a: s_t_l!($ty) = $ty::new($($a),+).into(); - let b: s_t_l!($ty) = $ty::new($($b),+).into(); - - let d = $ty::new($($d),+); - let r = $ty::from(unsafe { vec_max(a, b) }); - assert_eq!(d, r); - } - } - } + test_vec_min! { test_vec_min_f32x4, f32x4, + [-1.0, 0.0, 1.0, 2.0], + [2.0, 1.0, -1.0, -2.0], + [-1.0, 0.0, -1.0, -2.0] } test_vec_max! { test_vec_max_i32x4, i32x4, [-1, 0, 1, 2], @@ -6206,6 +6194,11 @@ mod tests { [2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0], [2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2] } + test_vec_max! { test_vec_max_f32x4, f32x4, + [-1.0, 0.0, 1.0, 2.0], + [2.0, 1.0, -1.0, -2.0], + [2.0, 1.0, 1.0, 2.0] } + macro_rules! test_vec_perm { {$name:ident, $shorttype:ident, $longtype:ident, diff --git a/crates/core_arch/src/powerpc/macros.rs b/crates/core_arch/src/powerpc/macros.rs index f697d4d257..394249050f 100644 --- a/crates/core_arch/src/powerpc/macros.rs +++ b/crates/core_arch/src/powerpc/macros.rs @@ -154,6 +154,9 @@ macro_rules! s_t_l { (f32x4) => { vector_float }; + (f64x2) => { + vector_double + }; } macro_rules! t_t_l { @@ -274,6 +277,36 @@ macro_rules! t_b { }; } +#[cfg(test)] +macro_rules! test_vec_min { + { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { + #[simd_test(enable = "altivec")] + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); + + let d = $ty::new($($d),+); + let r = $ty::from(unsafe { vec_min(a, b) }); + assert_eq!(d, r); + } + } +} + +#[cfg(test)] +macro_rules! test_vec_max { + { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { + #[simd_test(enable = "altivec")] + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); + + let d = $ty::new($($d),+); + let r = $ty::from(unsafe { vec_max(a, b) }); + assert_eq!(d, r); + } + } +} + pub(crate) use impl_vec_trait; pub(crate) use s_t_l; pub(crate) use t_b; @@ -281,3 +314,7 @@ pub(crate) use t_t_l; pub(crate) use t_t_s; pub(crate) use t_u; pub(crate) use test_impl; +#[cfg(test)] +pub(crate) use test_vec_max; +#[cfg(test)] +pub(crate) use test_vec_min; diff --git a/crates/core_arch/src/powerpc/vsx.rs b/crates/core_arch/src/powerpc/vsx.rs index 60cb2ad44c..0e2de24c8a 100644 --- a/crates/core_arch/src/powerpc/vsx.rs +++ b/crates/core_arch/src/powerpc/vsx.rs @@ -59,6 +59,11 @@ unsafe extern "unadjusted" { b: vector_signed_int, c: vector_unsigned_char, ) -> vector_signed_int; + + #[link_name = "llvm.ppc.vsx.xvmaxdp"] + fn xvmaxdp(a: vector_double, b: vector_double) -> vector_double; + #[link_name = "llvm.ppc.vsx.xvmindp"] + fn xvmindp(a: vector_double, b: vector_double) -> vector_double; } mod sealed { @@ -171,6 +176,40 @@ mod sealed { vec_mergeeo! { vector_unsigned_int, mergee, mergeo } vec_mergeeo! { vector_bool_int, mergee, mergeo } vec_mergeeo! { vector_float, mergee, mergeo } + + #[inline] + #[target_feature(enable = "vsx")] + #[cfg_attr(test, assert_instr(xvmindp))] + unsafe fn vec_xvmindp(a: vector_double, b: vector_double) -> vector_double { + xvmindp(a, b) + } + + #[inline] + #[target_feature(enable = "vsx")] + #[cfg_attr(test, assert_instr(xvmaxdp))] + unsafe fn vec_xvmaxdp(a: vector_double, b: vector_double) -> vector_double { + xvmaxdp(a, b) + } + + #[unstable(feature = "stdarch_powerpc", issue = "111145")] + impl super::altivec::sealed::VectorMin for vector_double { + type Result = vector_double; + #[inline] + #[target_feature(enable = "vsx")] + unsafe fn vec_min(self, b: vector_double) -> Self::Result { + vec_xvmindp(self, b) + } + } + + #[unstable(feature = "stdarch_powerpc", issue = "111145")] + impl super::altivec::sealed::VectorMax for vector_double { + type Result = vector_double; + #[inline] + #[target_feature(enable = "vsx")] + unsafe fn vec_max(self, b: vector_double) -> Self::Result { + vec_xvmaxdp(self, b) + } + } } /// Vector permute. @@ -234,6 +273,8 @@ mod tests { use crate::mem::transmute; use stdarch_test::simd_test; + use super::super::macros::*; + macro_rules! test_vec_xxpermdi { {$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vsx")] @@ -255,4 +296,7 @@ mod tests { test_vec_xxpermdi! {test_vec_xxpermdi_i64x2, i64x2, vector_signed_long, [0], [-1], [2], [-3]} test_vec_xxpermdi! {test_vec_xxpermdi_m64x2, m64x2, vector_bool_long, [false], [true], [false], [true]} test_vec_xxpermdi! {test_vec_xxpermdi_f64x2, f64x2, vector_double, [0.0], [1.0], [2.0], [3.0]} + + test_vec_min! { test_vec_min_f64x2, f64x2, [-1.0, 0.0], [2.0, 1.0], [-1.0, 0.0] } + test_vec_max! { test_vec_max_f64x2, f64x2, [-1.0, 0.0], [2.0, 1.0], [2.0, 1.0] } } From 0c23500e9bea8c2f81fcf09bbcde1287a34a0d84 Mon Sep 17 00:00:00 2001 From: Lei Huang Date: Thu, 18 Jun 2026 16:30:05 -0400 Subject: [PATCH 2/2] change feature guard to power8-vector as that's when the instructions was introduced --- crates/core_arch/src/powerpc/vsx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_arch/src/powerpc/vsx.rs b/crates/core_arch/src/powerpc/vsx.rs index 0e2de24c8a..0f34081fbd 100644 --- a/crates/core_arch/src/powerpc/vsx.rs +++ b/crates/core_arch/src/powerpc/vsx.rs @@ -179,14 +179,14 @@ mod sealed { #[inline] #[target_feature(enable = "vsx")] - #[cfg_attr(test, assert_instr(xvmindp))] + #[cfg_attr(all(test, target_feature = "power8-vector"), assert_instr(xvmindp))] unsafe fn vec_xvmindp(a: vector_double, b: vector_double) -> vector_double { xvmindp(a, b) } #[inline] #[target_feature(enable = "vsx")] - #[cfg_attr(test, assert_instr(xvmaxdp))] + #[cfg_attr(all(test, target_feature = "power8-vector"), assert_instr(xvmaxdp))] unsafe fn vec_xvmaxdp(a: vector_double, b: vector_double) -> vector_double { xvmaxdp(a, b) }