#![allow(dead_code)]
use core::simd::cmp::{SimdPartialEq, SimdPartialOrd};
use core::simd::u16x16;
use core::simd::u32x16;
use core::simd::u8x16;
#[inline]
fn load16_zero_pad(ptr: *const u8, valid_end: usize, align_end: usize) -> u8x16 {
debug_assert!(valid_end <= align_end);
debug_assert!(align_end <= 16);
let mut buf = [0u8; 16];
unsafe { core::ptr::copy_nonoverlapping(ptr, buf.as_mut_ptr(), 16) };
for i in valid_end..align_end {
buf[i] = 0;
}
u8x16::from(buf)
}
#[inline]
fn load16_partial(ptr: *const u8, n: usize) -> u8x16 {
debug_assert!(n > 0 && n < 16);
let mut buf = [0u8; 16];
unsafe { core::ptr::copy_nonoverlapping(ptr, buf.as_mut_ptr(), n) };
u8x16::from(buf)
}
#[inline]
fn load16(ptr: *const u8) -> u8x16 {
let mut buf = [0u8; 16];
unsafe { core::ptr::copy_nonoverlapping(ptr, buf.as_mut_ptr(), 16) };
u8x16::from(buf)
}
#[inline]
pub fn inode_find_child(
inode_ptr: *const u8,
symbols_offset: usize,
count: usize,
byte: u8,
) -> Option<usize> {
if count == 0 {
return None;
}
let valid_mask = ((1u32 << count) - 1) << symbols_offset;
let valid_end = symbols_offset + count;
let align_end = (valid_end + 7) & !7;
let vec = load16_zero_pad(inode_ptr, valid_end, align_end);
let byte_vec = u8x16::splat(byte);
let eq = vec.simd_eq(byte_vec);
let mask = eq.to_bitmask() as u32;
let hits = mask & valid_mask;
if hits != 0 {
return Some(hits.trailing_zeros() as usize - symbols_offset);
}
if symbols_offset + count > 16 {
let first_in_load1 = 16 - symbols_offset;
let remaining = count - first_in_load1;
let valid_mask2 = (1u32 << remaining) - 1;
let vec2 = unsafe {
let mut buf = [0u8; 16];
core::ptr::copy_nonoverlapping(inode_ptr.add(16), buf.as_mut_ptr(), 16);
u8x16::from(buf)
};
let eq2 = vec2.simd_eq(byte_vec);
let mask2 = eq2.to_bitmask() as u32;
let hits2 = mask2 & valid_mask2;
if hits2 != 0 {
return Some(first_in_load1 + hits2.trailing_zeros() as usize);
}
}
None
}
#[inline]
pub fn inode_find_child_lower_bound(
inode_ptr: *const u8,
symbols_offset: usize,
count: usize,
byte: u8,
) -> usize {
if count == 0 {
return 0;
}
let valid_mask = ((1u32 << count) - 1) << symbols_offset;
let valid_end = symbols_offset + count;
let align_end = (valid_end + 7) & !7;
let byte_vec = u8x16::splat(byte);
let vec = load16_zero_pad(inode_ptr, valid_end, align_end);
let lt = vec.simd_lt(byte_vec);
let mask = lt.to_bitmask() as u32;
let ge = (!mask) & valid_mask;
if ge != 0 {
return ge.trailing_zeros() as usize - symbols_offset;
}
if symbols_offset + count > 16 {
let first_in_load1 = 16 - symbols_offset;
let remaining = count - first_in_load1;
let valid_mask2 = (1u32 << remaining) - 1;
let vec2 = unsafe {
let mut buf = [0u8; 16];
core::ptr::copy_nonoverlapping(inode_ptr.add(16), buf.as_mut_ptr(), 16);
u8x16::from(buf)
};
let lt2 = vec2.simd_lt(byte_vec);
let mask2 = lt2.to_bitmask() as u32;
let ge2 = (!mask2) & valid_mask2;
if ge2 != 0 {
return first_in_load1 + ge2.trailing_zeros() as usize;
}
}
count
}
#[inline]
pub fn hnode_find_child(disc_ptr: *const u8, len: usize, byte: u8) -> Option<usize> {
if len == 0 {
return None;
}
let byte_vec = u8x16::splat(byte);
let mut offset = 0usize;
while offset + 16 <= len {
let vec = load16(unsafe { disc_ptr.add(offset) });
let eq = vec.simd_eq(byte_vec);
let mask = eq.to_bitmask() as u32;
if mask != 0 {
return Some(offset + mask.trailing_zeros() as usize);
}
offset += 16;
}
if offset < len {
let tail_len = len - offset;
let valid_mask = (1u32 << tail_len) - 1;
let vec = load16_partial(unsafe { disc_ptr.add(offset) }, tail_len);
let eq = vec.simd_eq(byte_vec);
let mask = eq.to_bitmask() as u32;
let hits = mask & valid_mask;
if hits != 0 {
return Some(offset + hits.trailing_zeros() as usize);
}
}
None
}
#[inline]
pub fn hnode_find_child_lower_bound(disc_ptr: *const u8, len: usize, byte: u8) -> usize {
if len == 0 {
return 0;
}
let byte_vec = u8x16::splat(byte);
let mut offset = 0usize;
while offset + 16 <= len {
let vec = load16(unsafe { disc_ptr.add(offset) });
let lt = vec.simd_lt(byte_vec);
let mask = lt.to_bitmask() as u32;
if mask != 0xFFFF {
let ge_mask = (!mask) & 0xFFFF;
return offset + ge_mask.trailing_zeros() as usize;
}
offset += 16;
}
if offset < len {
let tail_len = len - offset;
let valid_mask = (1u32 << tail_len) - 1;
let vec = load16_partial(unsafe { disc_ptr.add(offset) }, tail_len);
let lt = vec.simd_lt(byte_vec);
let mask = lt.to_bitmask() as u32;
let ge_mask = (!mask) & valid_mask;
if ge_mask != 0 {
return offset + ge_mask.trailing_zeros() as usize;
}
}
len
}
#[inline]
pub fn children_mask(children: &[u32; 16]) -> u16 {
let vec = u32x16::from(*children);
let zero = u32x16::splat(0);
let eq = vec.simd_ne(zero);
let empty = eq.to_bitmask() as u16; empty }
#[inline]
pub fn children_mask_u8(children: &[u8; 16]) -> u16 {
let vec = u8x16::from(*children);
let zero = u8x16::splat(0);
let ne = vec.simd_ne(zero);
ne.to_bitmask() as u16
}
#[inline]
pub fn children_mask_u16(children: &[u16; 16]) -> u16 {
let vec = u16x16::from(*children);
let zero = u16x16::splat(0);
let ne = vec.simd_ne(zero);
ne.to_bitmask() as u16
}
#[inline]
pub fn children_mask_u64(children: &[u64; 16]) -> u16 {
use std::simd::Simd;
let lo = Simd::<u64, 8>::from_slice(&children[0..8]);
let hi = Simd::<u64, 8>::from_slice(&children[8..16]);
let zero = Simd::<u64, 8>::splat(0);
let lo_ne = lo.simd_ne(zero);
let hi_ne = hi.simd_ne(zero);
let lo_mask = lo_ne.to_bitmask() as u16;
let hi_mask = (hi_ne.to_bitmask() as u16) << 8;
lo_mask | hi_mask
}
#[cfg(test)]
#[path = "tests/simd.rs"]
mod tests;