#![allow(unexpected_cfgs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
#[non_exhaustive]
pub enum InstructionSet {
Scalar,
#[cfg(feature = "std_simd")]
StdSimd,
Unknown,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86V1,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86V2,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86V3,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86V4,
#[cfg(all(feature = "neon", any(target_arch = "arm", target_arch = "aarch64")))]
NEON,
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
WASM32,
#[cfg(all(feature = "wasm", target_arch = "wasm64"))]
WASM64,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
SPIRV,
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86_detector;
impl InstructionSet {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn get() -> InstructionSet {
static DETECTOR: x86_detector::DetectInstructionSet = x86_detector::DetectInstructionSet::new();
DETECTOR.get_or_init()
}
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
pub fn get() -> InstructionSet {
InstructionSet::WASM32
}
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
pub fn get() -> InstructionSet {
InstructionSet::SPIRV
}
#[inline(always)]
pub const fn num_registers(&self) -> usize {
match self {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V1 => 8,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V2 | InstructionSet::X86V3 => 16,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V4 => 32,
#[cfg(all(feature = "neon", any(target_arch = "arm", target_arch = "aarch64")))]
InstructionSet::NEON => 32,
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
InstructionSet::WASM32 => 16,
#[cfg(all(feature = "wasm", target_arch = "wasm64"))]
InstructionSet::WASM64 => 16,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => 1,
_ => 1,
}
}
#[inline(always)]
pub const fn has_fma(&self) -> bool {
match self {
InstructionSet::Scalar => false,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V3 | InstructionSet::X86V4 => true,
#[cfg(all(feature = "neon", any(target_arch = "arm", target_arch = "aarch64")))]
InstructionSet::NEON => true,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => true,
_ => false,
}
}
#[inline(always)]
pub const fn is_simd(&self) -> bool {
match self {
InstructionSet::Scalar | InstructionSet::Unknown => false,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => false,
_ => true,
}
}
#[inline(always)]
pub const fn min(a: InstructionSet, b: InstructionSet) -> InstructionSet {
if (a as u8) < (b as u8) { a } else { b }
}
#[inline(always)]
pub const fn max(a: InstructionSet, b: InstructionSet) -> InstructionSet {
if (a as u8) > (b as u8) { a } else { b }
}
#[inline(always)]
pub const fn assert_eq(a: InstructionSet, b: InstructionSet) -> InstructionSet {
assert!((a as u8) == (b as u8), "InstructionSet equality assertion failed");
a
}
#[inline(always)]
pub const fn unaligned_is_cheap(self) -> bool {
match self {
InstructionSet::Scalar => true,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V1 | InstructionSet::X86V2 => false,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V3 | InstructionSet::X86V4 => true,
#[cfg(all(feature = "neon", any(target_arch = "arm", target_arch = "aarch64")))]
InstructionSet::NEON => true,
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
InstructionSet::WASM32 => false,
#[cfg(all(feature = "wasm", target_arch = "wasm64"))]
InstructionSet::WASM64 => false,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => true,
_ => false,
}
}
pub const fn unroll_factor(self) -> usize {
match self {
InstructionSet::Scalar => 4,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V1 | InstructionSet::X86V2 | InstructionSet::X86V3 => 4,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V4 => 8,
#[cfg(all(feature = "neon", any(target_arch = "arm", target_arch = "aarch64")))]
InstructionSet::NEON => 4,
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
InstructionSet::WASM32 => 2,
#[cfg(all(feature = "wasm", target_arch = "wasm64"))]
InstructionSet::WASM64 => 2,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => 1,
_ => 1,
}
}
pub const fn has_masked_operations(self) -> bool {
match self {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
InstructionSet::X86V4 => true,
_ => false,
}
}
pub const fn has_instruction_level_parallelism(self) -> bool {
match self {
#[cfg(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "arm",
target_arch = "aarch64"
))]
_ => true,
#[cfg(all(feature = "spirv", target_arch = "spirv"))]
InstructionSet::SPIRV => false,
_ => false,
}
}
}