1use std::sync::LazyLock;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum SimdSupport {
9 None,
10 Neon,
11 Sse,
12 Avx2,
13 Avx512,
14 Avx512FP16,
15 Lsx,
16 Lasx,
17}
18
19pub static SIMD_SUPPORT: LazyLock<SimdSupport> = LazyLock::new(|| {
21 #[cfg(all(target_arch = "aarch64", any(target_os = "ios", target_os = "tvos")))]
22 {
23 SimdSupport::Neon
25 }
26 #[cfg(all(
27 target_arch = "aarch64",
28 not(any(target_os = "ios", target_os = "tvos"))
29 ))]
30 {
31 if aarch64::has_neon_f16_support() {
32 SimdSupport::Neon
33 } else {
34 SimdSupport::None
35 }
36 }
37 #[cfg(target_arch = "x86_64")]
38 {
39 if x86::has_avx512() {
40 if x86::has_avx512_f16_support() {
41 SimdSupport::Avx512FP16
42 } else {
43 SimdSupport::Avx512
44 }
45 } else if is_x86_feature_detected!("avx2") {
46 SimdSupport::Avx2
47 } else {
48 SimdSupport::None
49 }
50 }
51 #[cfg(target_arch = "loongarch64")]
52 {
53 if loongarch64::has_lasx_support() {
54 SimdSupport::Lasx
55 } else if loongarch64::has_lsx_support() {
56 SimdSupport::Lsx
57 } else {
58 SimdSupport::None
59 }
60 }
61});
62
63#[cfg(target_arch = "x86_64")]
64mod x86 {
65 use core::arch::x86_64::__cpuid;
66
67 #[inline]
68 fn check_flag(x: usize, position: u32) -> bool {
69 x & (1 << position) != 0
70 }
71
72 pub fn has_avx512_f16_support() -> bool {
73 if !has_avx512() {
75 return false;
76 }
77
78 #[allow(unused_unsafe)]
83 let ext_cpuid_result = unsafe { __cpuid(7) };
84 check_flag(ext_cpuid_result.edx as usize, 23)
85 }
86
87 pub fn has_avx512() -> bool {
88 is_x86_feature_detected!("avx512f")
89 }
90}
91
92#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
97mod aarch64 {
98 pub fn has_neon_f16_support() -> bool {
99 true
101 }
102}
103
104#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
105mod aarch64 {
106 pub fn has_neon_f16_support() -> bool {
107 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
109 flags & libc::HWCAP_FPHP != 0
110 }
111}
112
113#[cfg(all(target_arch = "aarch64", target_os = "windows"))]
114mod aarch64 {
115 pub fn has_neon_f16_support() -> bool {
116 false
118 }
119}
120
121#[cfg(target_arch = "loongarch64")]
122mod loongarch64 {
123 pub fn has_lsx_support() -> bool {
124 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
126 flags & libc::HWCAP_LOONGARCH_LSX != 0
127 }
128 pub fn has_lasx_support() -> bool {
129 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
131 flags & libc::HWCAP_LOONGARCH_LASX != 0
132 }
133}
134
135#[cfg(all(target_arch = "aarch64", target_os = "android"))]
136mod aarch64 {
137 pub fn has_neon_f16_support() -> bool {
138 false
139 }
140}