Skip to content

Commit 1b392f9

Browse files
committed
PowerPC: Implement vec_cmp for VSX vector float/double
Implements VSX floating-point comparison intrinsics for PowerPC. Add support for vec_cmpeq, vec_cmpgt, and vec_cmpge operations on vector_float and vector_double types. Implementation uses VSX-specific instructions (xvcmpeqsp/xvcmpeqdp, xvcmpgtsp/xvcmpgtdp, xvcmpgesp/xvcmpgedp) for improved performance when VSX is available, while maintaining backward compatibility with AltiVec's vcmpgefp for vector_float when VSX is not enabled. AI Assited.
1 parent 6332f19 commit 1b392f9

2 files changed

Lines changed: 145 additions & 3 deletions

File tree

crates/core_arch/src/powerpc/altivec.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ unsafe extern "unadjusted" {
411411
}
412412

413413
#[macro_use]
414-
mod sealed {
414+
pub(crate) mod sealed {
415415
use super::*;
416416

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

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

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

847+
// Implement VectorCmpGe trait for vector_float using vcmpgefp (AltiVec)
848+
// This is overridden by vsx.rs when VSX is available
849+
#[cfg(not(target_feature = "vsx"))]
850+
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
851+
impl VectorCmpGe<vector_float> for vector_float {
852+
type Result = vector_bool_int;
853+
#[inline]
854+
#[target_feature(enable = "altivec")]
855+
unsafe fn vec_cmpge(self, b: vector_float) -> Self::Result {
856+
vec_vcmpgefp(self, b)
857+
}
858+
}
859+
841860
test_impl! { vec_vcmpequb(a: vector_unsigned_char, b: vector_unsigned_char) -> vector_bool_char [ vcmpequb, vcmpequb ] }
842861
test_impl! { vec_vcmpequh(a: vector_unsigned_short, b: vector_unsigned_short) -> vector_bool_short [ vcmpequh, vcmpequh ] }
843862
test_impl! { vec_vcmpequw(a: vector_unsigned_int, b: vector_unsigned_int) -> vector_bool_int [ vcmpequw, vcmpequw ] }
@@ -3779,8 +3798,11 @@ where
37793798
#[inline]
37803799
#[target_feature(enable = "altivec")]
37813800
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
3782-
pub unsafe fn vec_cmpge(a: vector_float, b: vector_float) -> vector_bool_int {
3783-
sealed::vec_vcmpgefp(a, b)
3801+
pub unsafe fn vec_cmpge<T, U>(a: T, b: U) -> <T as sealed::VectorCmpGe<U>>::Result
3802+
where
3803+
T: sealed::VectorCmpGe<U>,
3804+
{
3805+
a.vec_cmpge(b)
37843806
}
37853807

37863808
/// Vector cmpeq.

crates/core_arch/src/powerpc/vsx.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use crate::core_arch::powerpc::*;
1212
use crate::core_arch::simd::*;
13+
use crate::intrinsics::simd::*;
1314

1415
#[cfg(test)]
1516
use stdarch_test::assert_instr;
@@ -173,6 +174,31 @@ mod sealed {
173174
vec_mergeeo! { vector_float, mergee, mergeo }
174175
}
175176

177+
// Macro to implement VectorCmp* traits for vector types.
178+
macro_rules! impl_vsx_cmp {
179+
($trait_name:ident, $method_name:ident, $simd_op:ident, $vec_ty:ident, $result_ty:ident, $mask_ty:ident, $instr:ident) => {
180+
#[cfg(target_feature = "vsx")]
181+
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
182+
impl crate::core_arch::powerpc::altivec::sealed::$trait_name<$vec_ty> for $vec_ty {
183+
type Result = $result_ty;
184+
#[inline]
185+
#[target_feature(enable = "vsx")]
186+
#[cfg_attr(test, assert_instr($instr))]
187+
unsafe fn $method_name(self, b: $vec_ty) -> Self::Result {
188+
let result: $mask_ty = $simd_op(self, b);
189+
transmute(result)
190+
}
191+
}
192+
};
193+
}
194+
195+
impl_vsx_cmp!(VectorCmpEq, vec_cmpeq, simd_eq, vector_float, vector_bool_int, m32x4, xvcmpeqsp);
196+
impl_vsx_cmp!(VectorCmpEq, vec_cmpeq, simd_eq, vector_double, vector_bool_long, m64x2, xvcmpeqdp);
197+
impl_vsx_cmp!(VectorCmpGt, vec_cmpgt, simd_gt, vector_float, vector_bool_int, m32x4, xvcmpgtsp);
198+
impl_vsx_cmp!(VectorCmpGt, vec_cmpgt, simd_gt, vector_double, vector_bool_long, m64x2, xvcmpgtdp);
199+
impl_vsx_cmp!(VectorCmpGe, vec_cmpge, simd_ge, vector_float, vector_bool_int, m32x4, xvcmpgesp);
200+
impl_vsx_cmp!(VectorCmpGe, vec_cmpge, simd_ge, vector_double, vector_bool_long, m64x2, xvcmpgedp);
201+
176202
/// Vector permute.
177203
#[inline]
178204
#[target_feature(enable = "vsx")]
@@ -255,4 +281,98 @@ mod tests {
255281
test_vec_xxpermdi! {test_vec_xxpermdi_i64x2, i64x2, vector_signed_long, [0], [-1], [2], [-3]}
256282
test_vec_xxpermdi! {test_vec_xxpermdi_m64x2, m64x2, vector_bool_long, [false], [true], [false], [true]}
257283
test_vec_xxpermdi! {test_vec_xxpermdi_f64x2, f64x2, vector_double, [0.0], [1.0], [2.0], [3.0]}
284+
285+
#[simd_test(enable = "vsx")]
286+
fn test_vec_cmpeq_f32x4() {
287+
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
288+
let b = vector_float::from(f32x4::from_array([1.0, 3.0, 3.0, 5.0]));
289+
290+
unsafe {
291+
let result: vector_bool_int = vec_cmpeq(a, b);
292+
// Elements 0 and 2 are equal, elements 1 and 3 are not equal.
293+
// Equal elements should have all bits set (-1), non-equal should be 0.
294+
let result_i32: i32x4 = transmute(result);
295+
assert_eq!(result_i32.as_array()[0], -1i32);
296+
assert_eq!(result_i32.as_array()[1], 0i32);
297+
assert_eq!(result_i32.as_array()[2], -1i32);
298+
assert_eq!(result_i32.as_array()[3], 0i32);
299+
}
300+
}
301+
302+
#[simd_test(enable = "vsx")]
303+
fn test_vec_cmpeq_f64x2() {
304+
let a = vector_double::from(f64x2::from_array([1.0, 2.0]));
305+
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));
306+
307+
unsafe {
308+
let result: vector_bool_long = vec_cmpeq(a, b);
309+
// First element equal (1.0 == 1.0), second not equal (2.0 != 3.0).
310+
// Equal elements should have all bits set (-1), non-equal should be 0.
311+
let result_i64: i64x2 = transmute(result);
312+
assert_eq!(result_i64.as_array()[0], -1i64);
313+
assert_eq!(result_i64.as_array()[1], 0i64);
314+
}
315+
}
316+
317+
#[simd_test(enable = "vsx")]
318+
fn test_vec_cmpgt_f32x4() {
319+
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
320+
let b = vector_float::from(f32x4::from_array([0.0, 3.0, 3.0, 5.0]));
321+
322+
unsafe {
323+
let result: vector_bool_int = vec_cmpgt(a, b);
324+
// Element 0: 1.0 > 0.0 (true), Element 1: 2.0 > 3.0 (false)
325+
// Element 2: 3.0 > 3.0 (false), Element 3: 4.0 > 5.0 (false)
326+
let result_i32: i32x4 = transmute(result);
327+
assert_eq!(result_i32.as_array()[0], -1i32);
328+
assert_eq!(result_i32.as_array()[1], 0i32);
329+
assert_eq!(result_i32.as_array()[2], 0i32);
330+
assert_eq!(result_i32.as_array()[3], 0i32);
331+
}
332+
}
333+
334+
#[simd_test(enable = "vsx")]
335+
fn test_vec_cmpgt_f64x2() {
336+
let a = vector_double::from(f64x2::from_array([2.0, 1.0]));
337+
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));
338+
339+
unsafe {
340+
let result: vector_bool_long = vec_cmpgt(a, b);
341+
// First element: 2.0 > 1.0 (true), second: 1.0 > 3.0 (false)
342+
let result_i64: i64x2 = transmute(result);
343+
assert_eq!(result_i64.as_array()[0], -1i64);
344+
assert_eq!(result_i64.as_array()[1], 0i64);
345+
}
346+
}
347+
348+
#[simd_test(enable = "vsx")]
349+
fn test_vec_cmpge_f32x4() {
350+
let a = vector_float::from(f32x4::from_array([1.0, 2.0, 3.0, 4.0]));
351+
let b = vector_float::from(f32x4::from_array([0.0, 3.0, 3.0, 5.0]));
352+
353+
unsafe {
354+
let result: vector_bool_int = vec_cmpge(a, b);
355+
// Element 0: 1.0 >= 0.0 (true), Element 1: 2.0 >= 3.0 (false)
356+
// Element 2: 3.0 >= 3.0 (true), Element 3: 4.0 >= 5.0 (false)
357+
let result_i32: i32x4 = transmute(result);
358+
assert_eq!(result_i32.as_array()[0], -1i32);
359+
assert_eq!(result_i32.as_array()[1], 0i32);
360+
assert_eq!(result_i32.as_array()[2], -1i32);
361+
assert_eq!(result_i32.as_array()[3], 0i32);
362+
}
363+
}
364+
365+
#[simd_test(enable = "vsx")]
366+
fn test_vec_cmpge_f64x2() {
367+
let a = vector_double::from(f64x2::from_array([2.0, 3.0]));
368+
let b = vector_double::from(f64x2::from_array([1.0, 3.0]));
369+
370+
unsafe {
371+
let result: vector_bool_long = vec_cmpge(a, b);
372+
// First element: 2.0 >= 1.0 (true), second: 3.0 >= 3.0 (true)
373+
let result_i64: i64x2 = transmute(result);
374+
assert_eq!(result_i64.as_array()[0], -1i64);
375+
assert_eq!(result_i64.as_array()[1], -1i64);
376+
}
377+
}
258378
}

0 commit comments

Comments
 (0)