#![allow(unsafe_code)]
use core::sync::atomic::{
AtomicBool,
Ordering,
};
static AVX2_AVAILABLE: AtomicBool = AtomicBool::new(false);
static DETECTION_DONE: AtomicBool = AtomicBool::new(false);
pub fn detect_cpu_features() {
if DETECTION_DONE.load(Ordering::Relaxed) {
return;
}
#[cfg(all(target_arch = "x86_64", feature = "simd-avx2"))]
{
unsafe {
let result = core::arch::x86_64::__cpuid(1);
let osxsave = (result.ecx & (1 << 27)) != 0;
if osxsave {
let result = core::arch::x86_64::__cpuid_count(7, 0);
let avx2 = (result.ebx & (1 << 5)) != 0;
if avx2 {
let xcr0 = core::arch::x86_64::_xgetbv(0);
let avx_enabled = (xcr0 & 0x6) == 0x6;
if avx_enabled {
AVX2_AVAILABLE.store(true, Ordering::Relaxed);
}
}
}
}
}
DETECTION_DONE.store(true, Ordering::Relaxed);
}
pub fn has_avx2() -> bool {
detect_cpu_features();
AVX2_AVAILABLE.load(Ordering::Relaxed)
}
pub fn get_best_implementation() -> &'static str {
if has_avx2() { "avx2" } else { "portable" }
}
#[cfg(test)]
pub fn force_redetect() {
DETECTION_DONE.store(false, Ordering::Relaxed);
AVX2_AVAILABLE.store(false, Ordering::Relaxed);
detect_cpu_features();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detection_always_works() {
detect_cpu_features();
let _ = has_avx2();
let _ = get_best_implementation();
}
#[test]
fn test_redetection() {
force_redetect();
detect_cpu_features();
}
}