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 let ext_cpuid_result = unsafe { __cpuid(7) };
82 check_flag(ext_cpuid_result.edx as usize, 23)
83 }
84
85 pub fn has_avx512() -> bool {
86 is_x86_feature_detected!("avx512f")
87 }
88}
89
90#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
95mod aarch64 {
96 pub fn has_neon_f16_support() -> bool {
97 true
99 }
100}
101
102#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
103mod aarch64 {
104 pub fn has_neon_f16_support() -> bool {
105 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
107 flags & libc::HWCAP_FPHP != 0
108 }
109}
110
111#[cfg(all(target_arch = "aarch64", target_os = "windows"))]
112mod aarch64 {
113 pub fn has_neon_f16_support() -> bool {
114 false
116 }
117}
118
119#[cfg(target_arch = "loongarch64")]
120mod loongarch64 {
121 pub fn has_lsx_support() -> bool {
122 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
124 flags & libc::HWCAP_LOONGARCH_LSX != 0
125 }
126 pub fn has_lasx_support() -> bool {
127 let flags = unsafe { libc::getauxval(libc::AT_HWCAP) };
129 flags & libc::HWCAP_LOONGARCH_LASX != 0
130 }
131}
132
133#[cfg(all(target_arch = "aarch64", target_os = "android"))]
134mod aarch64 {
135 pub fn has_neon_f16_support() -> bool {
136 false
137 }
138}