Skip to content

Commit 97417b3

Browse files
Gelbpunktfolkertdev
authored andcommitted
Add LSX compare256 implementation
1 parent b16c537 commit 97417b3

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

zlib-rs/src/deflate/compare256.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ fn compare256(src0: &[u8; 256], src1: &[u8; 256]) -> usize {
2525
return unsafe { neon::compare256(src0, src1) };
2626
}
2727

28+
#[cfg(all(target_arch = "loongarch64", feature = "lsx"))]
29+
if crate::cpu_features::is_enabled_lsx() {
30+
return unsafe { lsx::compare256(src0, src1) };
31+
}
32+
2833
#[cfg(target_arch = "wasm32")]
2934
if crate::cpu_features::is_enabled_simd128() {
3035
return wasm32::compare256(src0, src1);
@@ -363,6 +368,59 @@ mod avx512 {
363368
}
364369
}
365370

371+
#[cfg(all(target_arch = "loongarch64", feature = "lsx"))]
372+
mod lsx {
373+
use core::arch::loongarch64::{lsx_vld, lsx_vmskltz_b, lsx_vpickve2gr_w, lsx_vseq_b};
374+
375+
#[target_feature(enable = "lsx")]
376+
pub fn compare256(src0: &[u8; 256], src1: &[u8; 256]) -> usize {
377+
let src0 = src0.chunks_exact(16);
378+
let src1 = src1.chunks_exact(16);
379+
380+
let mut len = 0;
381+
382+
unsafe {
383+
for (chunk0, chunk1) in src0.zip(src1) {
384+
let a = lsx_vld::<0>(chunk0.as_ptr() as *const i8);
385+
let b = lsx_vld::<0>(chunk1.as_ptr() as *const i8);
386+
387+
// element-wise compare of the 8-bit elements
388+
// 0xff if equal, otherwise 0
389+
let v = lsx_vseq_b(a, b);
390+
391+
// bootleg movemask implementation
392+
let mask = lsx_vpickve2gr_w::<0>(lsx_vmskltz_b(v));
393+
394+
if mask != 0xFFFF {
395+
let match_byte = mask.trailing_ones();
396+
return len + match_byte as usize;
397+
}
398+
399+
len += 16;
400+
}
401+
}
402+
403+
256
404+
}
405+
406+
#[test]
407+
fn test_compare256() {
408+
if crate::cpu_features::is_enabled_lsx() {
409+
let str1 = [b'a'; super::MAX_COMPARE_SIZE];
410+
let mut str2 = [b'a'; super::MAX_COMPARE_SIZE];
411+
412+
for i in 0..str1.len() {
413+
str2[i] = 0;
414+
415+
let match_len = unsafe { compare256(&str1, &str2) };
416+
assert_eq!(match_len, i);
417+
418+
str2[i] = b'a';
419+
}
420+
}
421+
}
422+
}
423+
366424
#[cfg(target_arch = "wasm32")]
367425
mod wasm32 {
368426
use core::arch::wasm32::{u8x16_bitmask, u8x16_eq, v128, v128_load};

0 commit comments

Comments
 (0)