From 16d060b962553383feef7c0edc7c53ad1e110b7d Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Wed, 15 Jul 2026 17:44:01 +0200 Subject: [PATCH] Add LSX compare256 implementation --- zlib-rs/src/deflate/compare256.rs | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/zlib-rs/src/deflate/compare256.rs b/zlib-rs/src/deflate/compare256.rs index c5344822..f4bcfc45 100644 --- a/zlib-rs/src/deflate/compare256.rs +++ b/zlib-rs/src/deflate/compare256.rs @@ -25,6 +25,11 @@ fn compare256(src0: &[u8; 256], src1: &[u8; 256]) -> usize { return unsafe { neon::compare256(src0, src1) }; } + #[cfg(all(target_arch = "loongarch64", feature = "lsx"))] + if crate::cpu_features::is_enabled_lsx() { + return unsafe { lsx::compare256(src0, src1) }; + } + #[cfg(target_arch = "wasm32")] if crate::cpu_features::is_enabled_simd128() { return wasm32::compare256(src0, src1); @@ -363,6 +368,59 @@ mod avx512 { } } +#[cfg(all(target_arch = "loongarch64", feature = "lsx"))] +mod lsx { + use core::arch::loongarch64::{lsx_vld, lsx_vmskltz_b, lsx_vpickve2gr_w, lsx_vseq_b}; + + #[target_feature(enable = "lsx")] + pub fn compare256(src0: &[u8; 256], src1: &[u8; 256]) -> usize { + let src0 = src0.chunks_exact(16); + let src1 = src1.chunks_exact(16); + + let mut len = 0; + + unsafe { + for (chunk0, chunk1) in src0.zip(src1) { + let a = lsx_vld::<0>(chunk0.as_ptr() as *const i8); + let b = lsx_vld::<0>(chunk1.as_ptr() as *const i8); + + // element-wise compare of the 8-bit elements + // 0xff if equal, otherwise 0 + let v = lsx_vseq_b(a, b); + + // bootleg movemask implementation + let mask = lsx_vpickve2gr_w::<0>(lsx_vmskltz_b(v)); + + if mask != 0xFFFF { + let match_byte = mask.trailing_ones(); + return len + match_byte as usize; + } + + len += 16; + } + } + + 256 + } + + #[test] + fn test_compare256() { + if crate::cpu_features::is_enabled_lsx() { + let str1 = [b'a'; super::MAX_COMPARE_SIZE]; + let mut str2 = [b'a'; super::MAX_COMPARE_SIZE]; + + for i in 0..str1.len() { + str2[i] = 0; + + let match_len = unsafe { compare256(&str1, &str2) }; + assert_eq!(match_len, i); + + str2[i] = b'a'; + } + } + } +} + #[cfg(target_arch = "wasm32")] mod wasm32 { use core::arch::wasm32::{u8x16_bitmask, u8x16_eq, v128, v128_load};