Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions crates/core_arch/src/powerpc/altivec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ unsafe extern "unadjusted" {
}

#[macro_use]
mod sealed {
pub(crate) mod sealed {
use super::*;

#[unstable(feature = "stdarch_powerpc", issue = "111145")]
Expand Down Expand Up @@ -836,8 +836,27 @@ mod sealed {

impl_vec_cmp! { [VectorCmpGt vec_cmpgt] ( vec_vcmpgtub, vec_vcmpgtsb, vec_vcmpgtuh, vec_vcmpgtsh, vec_vcmpgtuw, vec_vcmpgtsw ) }

test_impl! { vec_vcmpgefp(a: vector_float, b: vector_float) -> vector_bool_int [ vcmpgefp, vcmpgefp ] }
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
pub trait VectorCmpGe<Other> {
type Result;
unsafe fn vec_cmpge(self, b: Other) -> Self::Result;
}

// Implement VectorCmpGe trait for vector_float using simd_ge
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
impl VectorCmpGe<vector_float> for vector_float {
type Result = vector_bool_int;
#[inline]
#[target_feature(enable = "altivec")]
#[cfg_attr(all(test, not(target_feature = "vsx")), assert_instr(vcmpgefp))]
#[cfg_attr(all(test, target_feature = "power8-vector"), assert_instr(xvcmpgesp))]
unsafe fn vec_cmpge(self, b: vector_float) -> Self::Result {
let result: m32x4 = simd_ge(self, b);
transmute(result)
}
}

test_impl! { vec_vcmpgefp(a: vector_float, b: vector_float) -> vector_bool_int [ vcmpgefp, vcmpgefp ] }
test_impl! { vec_vcmpequb(a: vector_unsigned_char, b: vector_unsigned_char) -> vector_bool_char [ vcmpequb, vcmpequb ] }
test_impl! { vec_vcmpequh(a: vector_unsigned_short, b: vector_unsigned_short) -> vector_bool_short [ vcmpequh, vcmpequh ] }
test_impl! { vec_vcmpequw(a: vector_unsigned_int, b: vector_unsigned_int) -> vector_bool_int [ vcmpequw, vcmpequw ] }
Expand Down Expand Up @@ -3779,8 +3798,11 @@ where
#[inline]
#[target_feature(enable = "altivec")]
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
pub unsafe fn vec_cmpge(a: vector_float, b: vector_float) -> vector_bool_int {
sealed::vec_vcmpgefp(a, b)
pub unsafe fn vec_cmpge<T, U>(a: T, b: U) -> <T as sealed::VectorCmpGe<U>>::Result
where
T: sealed::VectorCmpGe<U>,
{
a.vec_cmpge(b)
}

/// Vector cmpeq.
Expand Down
158 changes: 158 additions & 0 deletions crates/core_arch/src/powerpc/vsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use crate::core_arch::powerpc::*;
use crate::core_arch::simd::*;
use crate::intrinsics::simd::*;

#[cfg(test)]
use stdarch_test::assert_instr;
Expand Down Expand Up @@ -173,6 +174,69 @@ mod sealed {
vec_mergeeo! { vector_float, mergee, mergeo }
}

// Macro to implement VectorCmp* traits for vector types.
macro_rules! impl_vsx_cmp {
($trait_name:ident, $method_name:ident, $simd_op:ident, $vec_ty:ident, $result_ty:ident, $mask_ty:ident, $instr:ident) => {
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
impl crate::core_arch::powerpc::altivec::sealed::$trait_name<$vec_ty> for $vec_ty {
type Result = $result_ty;
#[inline]
#[target_feature(enable = "vsx")]
#[cfg_attr(all(test, target_feature = "power8-vector"), assert_instr($instr))]
unsafe fn $method_name(self, b: $vec_ty) -> Self::Result {
let result: $mask_ty = $simd_op(self, b);
transmute(result)
}
}
};
}

impl_vsx_cmp!(
VectorCmpEq,
vec_cmpeq,
simd_eq,
vector_float,
vector_bool_int,
m32x4,
xvcmpeqsp
);
impl_vsx_cmp!(
VectorCmpEq,
vec_cmpeq,
simd_eq,
vector_double,
vector_bool_long,
m64x2,
xvcmpeqdp
);
impl_vsx_cmp!(
VectorCmpGt,
vec_cmpgt,
simd_gt,
vector_float,
vector_bool_int,
m32x4,
xvcmpgtsp
);
impl_vsx_cmp!(
VectorCmpGt,
vec_cmpgt,
simd_gt,
vector_double,
vector_bool_long,
m64x2,
xvcmpgtdp
);
impl_vsx_cmp!(
VectorCmpGe,
vec_cmpge,
simd_ge,
vector_double,
vector_bool_long,
m64x2,
xvcmpgedp
);

/// Vector permute.
#[inline]
#[target_feature(enable = "vsx")]
Expand Down Expand Up @@ -255,4 +319,98 @@ 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]}

#[simd_test(enable = "vsx")]
fn test_vec_cmpeq_f32x4() {
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
let b = vector_float::from(f32x4::from_array([1.0, 3.0, 3.0, 5.0]));

unsafe {
let result: vector_bool_int = vec_cmpeq(a, b);
// Elements 0 and 2 are equal, elements 1 and 3 are not equal.
// Equal elements should have all bits set (-1), non-equal should be 0.
let result_i32: i32x4 = transmute(result);
assert_eq!(result_i32.as_array()[0], -1i32);
assert_eq!(result_i32.as_array()[1], 0i32);
assert_eq!(result_i32.as_array()[2], -1i32);
assert_eq!(result_i32.as_array()[3], 0i32);
}
}

#[simd_test(enable = "vsx")]
fn test_vec_cmpeq_f64x2() {
let a = vector_double::from(f64x2::from_array([1.0, 2.0]));
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));

unsafe {
let result: vector_bool_long = vec_cmpeq(a, b);
// First element equal (1.0 == 1.0), second not equal (2.0 != 3.0).
// Equal elements should have all bits set (-1), non-equal should be 0.
let result_i64: i64x2 = transmute(result);
assert_eq!(result_i64.as_array()[0], -1i64);
assert_eq!(result_i64.as_array()[1], 0i64);
}
}

#[simd_test(enable = "vsx")]
fn test_vec_cmpgt_f32x4() {
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
let b = vector_float::from(f32x4::from_array([0.0, 3.0, 3.0, 5.0]));

unsafe {
let result: vector_bool_int = vec_cmpgt(a, b);
// Element 0: 1.0 > 0.0 (true), Element 1: 2.0 > 3.0 (false)
// Element 2: 3.0 > 3.0 (false), Element 3: 4.0 > 5.0 (false)
let result_i32: i32x4 = transmute(result);
assert_eq!(result_i32.as_array()[0], -1i32);
assert_eq!(result_i32.as_array()[1], 0i32);
assert_eq!(result_i32.as_array()[2], 0i32);
assert_eq!(result_i32.as_array()[3], 0i32);
}
}

#[simd_test(enable = "vsx")]
fn test_vec_cmpgt_f64x2() {
let a = vector_double::from(f64x2::from_array([2.0, 1.0]));
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));

unsafe {
let result: vector_bool_long = vec_cmpgt(a, b);
// First element: 2.0 > 1.0 (true), second: 1.0 > 3.0 (false)
let result_i64: i64x2 = transmute(result);
assert_eq!(result_i64.as_array()[0], -1i64);
assert_eq!(result_i64.as_array()[1], 0i64);
}
}

#[simd_test(enable = "vsx")]
fn test_vec_cmpge_f32x4() {
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
let b = vector_float::from(f32x4::from_array([0.0, 3.0, 3.0, 5.0]));

unsafe {
let result: vector_bool_int = vec_cmpge(a, b);
// Element 0: 1.0 >= 0.0 (true), Element 1: 2.0 >= 3.0 (false)
// Element 2: 3.0 >= 3.0 (true), Element 3: 4.0 >= 5.0 (false)
let result_i32: i32x4 = transmute(result);
assert_eq!(result_i32.as_array()[0], -1i32);
assert_eq!(result_i32.as_array()[1], 0i32);
assert_eq!(result_i32.as_array()[2], -1i32);
assert_eq!(result_i32.as_array()[3], 0i32);
}
}

#[simd_test(enable = "vsx")]
fn test_vec_cmpge_f64x2() {
let a = vector_double::from(f64x2::from_array([2.0, 3.0]));
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));

unsafe {
let result: vector_bool_long = vec_cmpge(a, b);
// First element: 2.0 >= 1.0 (true), second: 3.0 >= 3.0 (true)
let result_i64: i64x2 = transmute(result);
assert_eq!(result_i64.as_array()[0], -1i64);
assert_eq!(result_i64.as_array()[1], -1i64);
}
}
}
Loading