#[cfg(target_arch = "x86_64")]
#[cfg(target_arch = "aarch64")]
use std::arch::aarch64::*;
#[repr(align(64))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct CpuFeatures {
pub sse2: bool,
pub sse3: bool,
pub ssse3: bool,
pub sse4_1: bool,
pub sse4_2: bool,
pub avx: bool,
pub avx2: bool,
pub fma: bool,
pub avx512f: bool,
pub neon: bool,
pub sve: bool,
}
impl CpuFeatures {
pub fn all_enabled() -> Self {
Self {
sse2: true,
sse3: true,
ssse3: true,
sse4_1: true,
sse4_2: true,
avx: true,
avx2: true,
fma: true,
avx512f: true,
neon: true,
sve: true,
}
}
}
#[cfg(target_arch = "x86_64")]
fn detect_x86_features() -> CpuFeatures {
let mut features = CpuFeatures {
sse2: true, ..Default::default()
};
if std::is_x86_feature_detected!("sse3") {
features.sse3 = true;
}
if std::is_x86_feature_detected!("ssse3") {
features.ssse3 = true;
}
if std::is_x86_feature_detected!("sse4.1") {
features.sse4_1 = true;
}
if std::is_x86_feature_detected!("sse4.2") {
features.sse4_2 = true;
}
if std::is_x86_feature_detected!("avx") {
features.avx = true;
}
if std::is_x86_feature_detected!("avx2") {
features.avx2 = true;
}
if std::is_x86_feature_detected!("fma") {
features.fma = true;
}
if std::is_x86_feature_detected!("avx512f") {
features.avx512f = true;
}
features
}
#[cfg(target_arch = "aarch64")]
fn detect_aarch64_features() -> CpuFeatures {
#[cfg(target_feature = "sve")]
{
CpuFeatures {
neon: true,
sve: true,
..Default::default()
}
}
#[cfg(not(target_feature = "sve"))]
{
CpuFeatures {
neon: true,
..Default::default()
}
}
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
fn detect_other_features() -> CpuFeatures {
CpuFeatures::default()
}
pub fn detect_cpu_features() -> CpuFeatures {
#[cfg(target_arch = "x86_64")]
return detect_x86_features();
#[cfg(target_arch = "aarch64")]
return detect_aarch64_features();
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
return detect_other_features();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cpu_feature_detection() {
let features = detect_cpu_features();
#[cfg(target_arch = "x86_64")]
{
assert!(features.sse2);
}
#[cfg(target_arch = "aarch64")]
{
assert!(features.neon);
}
}
}