#[cfg(not(all( httparse_simd, any( target_arch = "x86", target_arch = "x86_64", ), )))] mod fallback; #[cfg(not(all( httparse_simd, any( target_arch = "x86", target_arch = "x86_64", ), )))] pub use self::fallback::*; #[cfg(all( httparse_simd, any( target_arch = "x86", target_arch = "x86_64", ), ))] mod sse42; #[cfg(all( httparse_simd, any( httparse_simd_target_feature_avx2, not(httparse_simd_target_feature_sse42), ), any( target_arch = "x86", target_arch = "x86_64", ), ))] mod avx2; #[cfg(all( httparse_simd, any( target_arch = "x86", target_arch = "x86_64", ), ))] pub const SSE_42: usize = 1; #[cfg(all( httparse_simd, any(not(httparse_simd_target_feature_sse42), httparse_simd_target_feature_avx2), any( target_arch = "x86", target_arch = "x86_64", ), ))] pub const AVX_2: usize = 2; #[cfg(all( httparse_simd, any( not(httparse_simd_target_feature_sse42), httparse_simd_target_feature_avx2, test, ), any( target_arch = "x86", target_arch = "x86_64", ), ))] pub const AVX_2_AND_SSE_42: usize = 3; #[cfg(all( httparse_simd, any( target_arch = "x86", target_arch = "x86_64", ), ))] const NONE: usize = std::usize::MAX; #[cfg(all( httparse_simd, not(any( httparse_simd_target_feature_sse42, httparse_simd_target_feature_avx2, )), any( target_arch = "x86", target_arch = "x86_64", ), ))] mod runtime { //! Runtime detection of simd features. Used when the build script //! doesn't notice any target features at build time. //! //! While `is_x86_feature_detected!` has it's own caching built-in, //! at least in 1.27.0, the functions don't inline, leaving using it //! actually *slower* than just using the scalar fallback. use core::sync::atomic::{AtomicUsize, Ordering}; static FEATURE: AtomicUsize = AtomicUsize::new(0); const INIT: usize = 0; pub fn detect() -> usize { let feat = FEATURE.load(Ordering::Relaxed); if feat == INIT { if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") { if is_x86_feature_detected!("sse4.2") { FEATURE.store(super::AVX_2_AND_SSE_42, Ordering::Relaxed); return super::AVX_2_AND_SSE_42; } else { FEATURE.store(super::AVX_2, Ordering::Relaxed); return super::AVX_2; } } else if is_x86_feature_detected!("sse4.2") { FEATURE.store(super::SSE_42, Ordering::Relaxed); return super::SSE_42; } else { FEATURE.store(super::NONE, Ordering::Relaxed); } } feat } pub fn match_uri_vectored(bytes: &mut crate::iter::Bytes) { unsafe { match detect() { super::SSE_42 => super::sse42::parse_uri_batch_16(bytes), super::AVX_2 => { super::avx2::parse_uri_batch_32(bytes); }, super::AVX_2_AND_SSE_42 => { if let super::avx2::Scan::Found = super::avx2::parse_uri_batch_32(bytes) { return; } super::sse42::parse_uri_batch_16(bytes) }, _ => () } } // else do nothing } pub fn match_header_value_vectored(bytes: &mut crate::iter::Bytes) { unsafe { match detect() { super::SSE_42 => super::sse42::match_header_value_batch_16(bytes), super::AVX_2 => { super::avx2::match_header_value_batch_32(bytes); }, super::AVX_2_AND_SSE_42 => { if let super::avx2::Scan::Found = super::avx2::match_header_value_batch_32(bytes) { return; } super::sse42::match_header_value_batch_16(bytes) }, _ => () } } // else do nothing } } #[cfg(all( httparse_simd, not(any( httparse_simd_target_feature_sse42, httparse_simd_target_feature_avx2, )), any( target_arch = "x86", target_arch = "x86_64", ), ))] pub use self::runtime::*; #[cfg(all( httparse_simd, httparse_simd_target_feature_sse42, not(httparse_simd_target_feature_avx2), any( target_arch = "x86", target_arch = "x86_64", ), ))] mod sse42_compile_time { pub fn match_uri_vectored(bytes: &mut crate::iter::Bytes) { if detect() == super::SSE_42 { unsafe { super::sse42::parse_uri_batch_16(bytes); } } // else do nothing } pub fn match_header_value_vectored(bytes: &mut crate::iter::Bytes) { if detect() == super::SSE_42 { unsafe { super::sse42::match_header_value_batch_16(bytes); } } // else do nothing } pub fn detect() -> usize { if is_x86_feature_detected!("sse4.2") { super::SSE_42 } else { super::NONE } } } #[cfg(all( httparse_simd, httparse_simd_target_feature_sse42, not(httparse_simd_target_feature_avx2), any( target_arch = "x86", target_arch = "x86_64", ), ))] pub use self::sse42_compile_time::*; #[cfg(all( httparse_simd, httparse_simd_target_feature_avx2, any( target_arch = "x86", target_arch = "x86_64", ), ))] mod avx2_compile_time { pub fn match_uri_vectored(bytes: &mut crate::iter::Bytes) { // do both, since avx2 only works when bytes.len() >= 32 if detect() == super::AVX_2_AND_SSE_42 { unsafe { super::avx2::parse_uri_batch_32(bytes); } } if detect() == super::SSE_42 { unsafe { super::sse42::parse_uri_batch_16(bytes); } } // else do nothing } pub fn match_header_value_vectored(bytes: &mut crate::iter::Bytes) { // do both, since avx2 only works when bytes.len() >= 32 if detect() == super::AVX_2_AND_SSE_42 { let scanned = unsafe { super::avx2::match_header_value_batch_32(bytes) }; if let super::avx2::Scan::Found = scanned { return; } } if detect() == super::SSE_42 { unsafe { super::sse42::match_header_value_batch_16(bytes); } } // else do nothing } pub fn detect() -> usize { if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") { super::AVX_2_AND_SSE_42 } else if is_x86_feature_detected!("sse4.2") { super::SSE_42 } else { super::NONE } } } #[cfg(all( httparse_simd, httparse_simd_target_feature_avx2, any( target_arch = "x86", target_arch = "x86_64", ), ))] pub use self::avx2_compile_time::*;