#![allow(unused_unsafe)]
pub(crate) mod scalar;
#[cfg(all(
target_arch = "aarch64",
target_endian = "little",
feature = "kernel-neon"
))]
pub(crate) mod neon;
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
pub(crate) mod sse2;
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-avx2"
))]
pub(crate) mod avx2_bmi2;
#[cfg(all(
target_arch = "wasm32",
target_feature = "simd128",
feature = "kernel-simd128"
))]
pub(crate) mod simd128;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum FastpathKernel {
Scalar,
#[cfg(all(
target_arch = "aarch64",
target_endian = "little",
feature = "kernel-neon"
))]
Neon,
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
Sse2,
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
Sse42,
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-avx2"
))]
Avx2Bmi2,
#[cfg(all(
target_arch = "wasm32",
target_feature = "simd128",
feature = "kernel-simd128"
))]
Simd128,
}
#[inline]
pub(crate) fn select_kernel() -> FastpathKernel {
#[cfg(feature = "std")]
{
use std::sync::OnceLock;
static CACHE: OnceLock<FastpathKernel> = OnceLock::new();
*CACHE.get_or_init(detect_kernel_uncached)
}
#[cfg(not(feature = "std"))]
{
detect_kernel_uncached()
}
}
#[inline]
#[cfg_attr(
all(
target_arch = "wasm32",
target_feature = "simd128",
feature = "kernel-simd128"
),
allow(unreachable_code)
)]
fn detect_kernel_uncached() -> FastpathKernel {
#[cfg(all(
feature = "std",
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-avx2"
))]
{
if std::is_x86_feature_detected!("avx2") && std::is_x86_feature_detected!("bmi2") {
return FastpathKernel::Avx2Bmi2;
}
}
#[cfg(all(
feature = "std",
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
{
if std::is_x86_feature_detected!("sse4.2") {
return FastpathKernel::Sse42;
}
if std::is_x86_feature_detected!("sse2") {
return FastpathKernel::Sse2;
}
}
#[cfg(all(
feature = "std",
target_arch = "aarch64",
target_endian = "little",
feature = "kernel-neon"
))]
{
if std::arch::is_aarch64_feature_detected!("neon") {
return FastpathKernel::Neon;
}
}
#[cfg(all(
not(feature = "std"),
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-avx2"
))]
{
if cfg!(target_feature = "avx2") && cfg!(target_feature = "bmi2") {
return FastpathKernel::Avx2Bmi2;
}
}
#[cfg(all(
not(feature = "std"),
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
{
if cfg!(target_feature = "sse4.2") {
return FastpathKernel::Sse42;
}
if cfg!(target_feature = "sse2") {
return FastpathKernel::Sse2;
}
}
#[cfg(all(
not(feature = "std"),
target_arch = "aarch64",
target_endian = "little",
feature = "kernel-neon"
))]
{
if cfg!(target_feature = "neon") {
return FastpathKernel::Neon;
}
}
#[cfg(all(
target_arch = "wasm32",
target_feature = "simd128",
feature = "kernel-simd128"
))]
{
return FastpathKernel::Simd128;
}
FastpathKernel::Scalar
}
#[inline]
pub(crate) unsafe fn dispatch_common_prefix_len_ptr(
lhs: *const u8,
rhs: *const u8,
max: usize,
) -> usize {
unsafe { dispatch_common_prefix_len_ptr_with_kernel(select_kernel(), lhs, rhs, max) }
}
#[inline(always)]
pub(crate) unsafe fn dispatch_common_prefix_len_ptr_with_kernel(
kernel: FastpathKernel,
lhs: *const u8,
rhs: *const u8,
max: usize,
) -> usize {
match kernel {
FastpathKernel::Scalar => unsafe { scalar::common_prefix_len_ptr(lhs, rhs, max) },
#[cfg(all(
target_arch = "aarch64",
target_endian = "little",
feature = "kernel-neon"
))]
FastpathKernel::Neon => unsafe { neon::common_prefix_len_ptr(lhs, rhs, max) },
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-sse"
))]
FastpathKernel::Sse2 | FastpathKernel::Sse42 => unsafe {
sse2::common_prefix_len_ptr(lhs, rhs, max)
},
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
feature = "kernel-avx2"
))]
FastpathKernel::Avx2Bmi2 => unsafe { avx2_bmi2::common_prefix_len_ptr(lhs, rhs, max) },
#[cfg(all(
target_arch = "wasm32",
target_feature = "simd128",
feature = "kernel-simd128"
))]
FastpathKernel::Simd128 => unsafe { simd128::common_prefix_len_ptr(lhs, rhs, max) },
}
}
#[cfg(test)]
mod tests;