Skip to content

Commit 44a03e6

Browse files
Merge pull request #533 from heiher/swizzle-dyn-loong64
Optimize `swizzle_dyn` for LoongArch64 with N is 16 or 32
2 parents d7a525f + 30bdfe3 commit 44a03e6

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

crates/core_simd/src/swizzle_dyn.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ impl<const N: usize> Simd<u8, N> {
4848
target_endian = "little"
4949
))]
5050
16 => transize(armv7_neon_swizzle_u8x16, self, idxs),
51+
#[cfg(all(target_arch = "loongarch64", target_feature = "lsx"))]
52+
16 => transize(loong64_lsx_swizzle, self, idxs),
5153
#[cfg(all(target_feature = "avx2", not(target_feature = "avx512vbmi")))]
5254
32 => transize(avx2_pshufb, self, idxs),
5355
#[cfg(all(target_feature = "avx512vl", target_feature = "avx512vbmi"))]
@@ -62,6 +64,8 @@ impl<const N: usize> Simd<u8, N> {
6264
};
6365
transize(swizzler, self, idxs)
6466
}
67+
#[cfg(all(target_arch = "loongarch64", target_feature = "lasx"))]
68+
32 => transize(loong64_lasx_swizzle, self, idxs),
6569
// Notable absence: avx512bw pshufb shuffle
6670
#[cfg(all(target_feature = "avx512vl", target_feature = "avx512vbmi"))]
6771
64 => {
@@ -220,6 +224,38 @@ unsafe fn avx2_pshufb(bytes: Simd<u8, 32>, idxs: Simd<u8, 32>) -> Simd<u8, 32> {
220224
}
221225
}
222226

227+
/// LoongArch64 LSX supports swizzling `u8x16`
228+
///
229+
/// # Safety
230+
/// This requires LoongArch LSX to work
231+
#[cfg(all(target_arch = "loongarch64", target_feature = "lsx"))]
232+
unsafe fn loong64_lsx_swizzle(bytes: Simd<u8, 16>, idxs: Simd<u8, 16>) -> Simd<u8, 16> {
233+
use core::arch::loongarch64::{lsx_vand_v, lsx_vshuf_b, lsx_vslei_bu};
234+
// SAFETY: Caller promised loongarch lsx support
235+
unsafe {
236+
let bytes = lsx_vshuf_b(bytes.into(), bytes.into(), idxs.into());
237+
let mask = lsx_vslei_bu::<15>(idxs.into());
238+
lsx_vand_v(bytes, mask).into()
239+
}
240+
}
241+
242+
/// LoongArch64 LASX supports swizzling `u8x32`
243+
///
244+
/// # Safety
245+
/// This requires LoongArch LASX to work
246+
#[cfg(all(target_arch = "loongarch64", target_feature = "lasx"))]
247+
unsafe fn loong64_lasx_swizzle(bytes: Simd<u8, 32>, idxs: Simd<u8, 32>) -> Simd<u8, 32> {
248+
use core::arch::loongarch64::{lasx_xvand_v, lasx_xvpermi_q, lasx_xvshuf_b, lasx_xvslei_bu};
249+
// SAFETY: Caller promised loongarch lasx support
250+
unsafe {
251+
let lolo = lasx_xvpermi_q::<0x00>(bytes.into(), bytes.into());
252+
let hihi = lasx_xvpermi_q::<0x11>(bytes.into(), bytes.into());
253+
let bytes = lasx_xvshuf_b(hihi, lolo, idxs.into());
254+
let mask = lasx_xvslei_bu::<31>(idxs.into());
255+
lasx_xvand_v(bytes, mask).into()
256+
}
257+
}
258+
223259
/// This sets up a call to an architecture-specific function, and in doing so
224260
/// it persuades rustc that everything is the correct size. Which it is.
225261
/// This would not be needed if one could convince Rust that, by matching on N,

0 commit comments

Comments
 (0)