#[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
macro_rules! x86_isa_detected {
($feat:tt) => {
is_x86_feature_detected!($feat)
};
}
#[cfg(all(not(feature = "std"), any(target_arch = "x86", target_arch = "x86_64")))]
macro_rules! x86_isa_detected {
($feat:tt) => {
cfg!(target_feature = $feat)
};
}
#[cfg_attr(not(feature = "std"), allow(dead_code))]
#[derive(Copy, Clone, PartialEq, Eq)]
pub(super) enum ForcedIsa {
Auto,
Scalar,
Fma,
Avx512F,
Avx512Vnni,
Avx512Bf16,
Neon,
Simd128,
}
#[cfg(feature = "std")]
pub(super) fn forced_isa() -> ForcedIsa {
match std::env::var("GEMMKIT_REQUIRE_ISA") {
Err(_) => ForcedIsa::Auto,
Ok(s) => {
let t = s.trim();
if t.is_empty() || t.eq_ignore_ascii_case("auto") {
ForcedIsa::Auto
} else if t.eq_ignore_ascii_case("scalar") {
ForcedIsa::Scalar
} else if t.eq_ignore_ascii_case("fma") || t.eq_ignore_ascii_case("avx2") {
ForcedIsa::Fma
} else if t.eq_ignore_ascii_case("avx512f") {
ForcedIsa::Avx512F
} else if t.eq_ignore_ascii_case("avx512vnni") || t.eq_ignore_ascii_case("vnni") {
ForcedIsa::Avx512Vnni
} else if t.eq_ignore_ascii_case("avx512bf16") || t.eq_ignore_ascii_case("bf16") {
ForcedIsa::Avx512Bf16
} else if t.eq_ignore_ascii_case("neon") {
ForcedIsa::Neon
} else if t.eq_ignore_ascii_case("simd128") || t.eq_ignore_ascii_case("wasm") {
ForcedIsa::Simd128
} else {
panic!(
"GEMMKIT_REQUIRE_ISA: unknown value `{t}` (expected scalar|fma|avx512f|avx512vnni|avx512bf16|neon|simd128|auto)"
)
}
}
}
}
#[cfg(not(feature = "std"))]
pub(super) fn forced_isa() -> ForcedIsa {
ForcedIsa::Auto
}
macro_rules! memoized_select {
($static:ident, $accessor:ident, $ty:ty, $select:ident, $doc:literal) => {
#[cfg(feature = "std")]
static $static: OnceLock<$ty> = OnceLock::new();
#[doc = $doc]
#[inline]
fn $accessor() -> $ty {
#[cfg(feature = "std")]
{
*$static.get_or_init($select)
}
#[cfg(not(feature = "std"))]
{
$select()
}
}
};
($static:ident, $accessor:ident, $ty:ty, $select:ident, $doc:literal, $feat:literal) => {
#[cfg(all(feature = "std", feature = $feat))]
static $static: OnceLock<$ty> = OnceLock::new();
#[doc = $doc]
#[cfg(feature = $feat)]
#[inline]
fn $accessor() -> $ty {
#[cfg(feature = "std")]
{
*$static.get_or_init($select)
}
#[cfg(not(feature = "std"))]
{
$select()
}
}
};
}