use super::{Scalar, Target, Target1, Target2, Target3, V3, get_or_set_architecture};
use crate::{
Architecture, SIMDVector,
arch::{self, Dispatched1, Dispatched2, Dispatched3, FTarget1, FTarget2, FTarget3, Hidden},
lifetime::AddLifetime,
};
macro_rules! maybe_miri {
($mod:ident, $type:ident, $T:ty, $N:literal) => {
#[cfg(miri)]
#[allow(non_camel_case_types)]
pub type $type = crate::Emulated<$T, $N, V4>;
#[cfg(not(miri))]
pub use $mod::$type;
};
}
pub mod f16x8_;
maybe_miri!(f16x8_, f16x8, half::f16, 8);
pub mod f16x16_;
maybe_miri!(f16x16_, f16x16, half::f16, 16);
pub mod f32x4_;
maybe_miri!(f32x4_, f32x4, f32, 4);
pub mod f32x8_;
maybe_miri!(f32x8_, f32x8, f32, 8);
pub mod f32x16_;
maybe_miri!(f32x16_, f32x16, f32, 16);
pub mod i8x16_;
maybe_miri!(i8x16_, i8x16, i8, 16);
pub mod i8x32_;
maybe_miri!(i8x32_, i8x32, i8, 32);
pub mod i8x64_;
maybe_miri!(i8x64_, i8x64, i8, 64);
pub mod i16x8_;
maybe_miri!(i16x8_, i16x8, i16, 8);
pub mod i16x16_;
maybe_miri!(i16x16_, i16x16, i16, 16);
pub mod i16x32_;
maybe_miri!(i16x32_, i16x32, i16, 32);
pub mod i32x4_;
maybe_miri!(i32x4_, i32x4, i32, 4);
pub mod i32x8_;
maybe_miri!(i32x8_, i32x8, i32, 8);
pub mod i32x16_;
maybe_miri!(i32x16_, i32x16, i32, 16);
pub mod u8x16_;
maybe_miri!(u8x16_, u8x16, u8, 16);
pub mod u8x32_;
maybe_miri!(u8x32_, u8x32, u8, 32);
pub mod u8x64_;
maybe_miri!(u8x64_, u8x64, u8, 64);
pub mod u32x4_;
maybe_miri!(u32x4_, u32x4, u32, 4);
pub mod u32x8_;
maybe_miri!(u32x8_, u32x8, u32, 8);
pub mod u32x16_;
maybe_miri!(u32x16_, u32x16, u32, 16);
pub mod u64x2_;
maybe_miri!(u64x2_, u64x2, u64, 2);
pub mod u64x4_;
maybe_miri!(u64x4_, u64x4, u64, 4);
mod conversion;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct V4(Hidden);
impl arch::Sealed for V4 {}
macro_rules! v4_features {
($($args:tt)*) => {
#[cfg_attr(
not(miri),
target_feature(
enable = "avx2,avx,bmi1,bmi2,f16c,fma,lzcnt,movbe,xsave,avx512f,avx512bw,avx512cd,avx512vl,avx512dq,avx512vnni,avx512bitalg,avx512vpopcntdq,avx512vbmi"
)
)]
$($args)*
}
}
impl V4 {
pub const unsafe fn new() -> Self {
Self(Hidden)
}
pub fn new_checked() -> Option<Self> {
unsafe { Self::new_checked_with(get_or_set_architecture!()) }
}
pub fn new_checked_miri() -> Option<Self> {
if cfg!(miri) {
V3::new_checked().map(|_| {
unsafe { Self::new() }
})
} else {
Self::new_checked()
}
}
pub fn retarget(self) -> V3 {
unsafe { V3::new() }
}
#[cfg(test)]
pub(crate) fn new_checked_uncached() -> Option<Self> {
match unsafe { Self::new_checked_with(super::arch_number()) } {
Some(v) => Some(v),
None => {
if unsafe { Self::new_checked_with(super::test_arch_number()) }.is_some() {
panic!(
"V4 architecture was requested but is not compatible on the current hardware"
);
} else {
None
}
}
}
}
unsafe fn new_checked_with(version: u64) -> Option<Self> {
if version >= super::ARCH_V4 {
Some(unsafe { Self::new() })
} else {
None
}
}
v4_features! {
pub(super) unsafe fn run_with<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
f.run(self)
}
}
v4_features! {
#[inline]
pub(super) unsafe fn run_with_inline<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
f.run(self)
}
}
v4_features! {
pub(super) unsafe fn run_with_1<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
f.run(self, x0)
}
}
v4_features! {
#[inline]
pub(super) unsafe fn run_with_1_inline<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
f.run(self, x0)
}
}
v4_features! {
pub(super) unsafe fn run_with_2<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
f.run(self, x0, x1)
}
}
v4_features! {
#[inline]
pub(super) unsafe fn run_with_2_inline<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
f.run(self, x0, x1)
}
}
v4_features! {
pub(super) unsafe fn run_with_3<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
f.run(self, x0, x1, x2)
}
}
v4_features! {
#[inline]
pub(super) unsafe fn run_with_3_inline<F, T0, T1, T2, R>(
self,
f: F,
x0: T0,
x1: T1,
x2: T2,
) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
f.run(self, x0, x1, x2)
}
}
v4_features! {
pub(super) unsafe fn run_function_with_1<F, T0, R>(self, x0: T0::Of<'_>) -> R
where
T0: AddLifetime,
F: for<'a> FTarget1<Self, R, T0::Of<'a>>,
{
F::run(self, x0)
}
}
v4_features! {
pub(super) unsafe fn run_function_with_2<F, T0, T1, R>(
self,
x0: T0::Of<'_>,
x1: T1::Of<'_>,
) -> R
where
T0: AddLifetime,
T1: AddLifetime,
F: for<'a, 'b> FTarget2<Self, R, T0::Of<'a>, T1::Of<'b>>,
{
F::run(self, x0, x1)
}
}
v4_features! {
pub(super) unsafe fn run_function_with_3<F, T0, T1, T2, R>(
self,
x0: T0::Of<'_>,
x1: T1::Of<'_>,
x2: T2::Of<'_>,
) -> R
where
T0: AddLifetime,
T1: AddLifetime,
T2: AddLifetime,
F: for<'a, 'b, 'c> FTarget3<Self, R, T0::Of<'a>, T1::Of<'b>, T2::Of<'c>>,
{
F::run(self, x0, x1, x2)
}
}
}
impl Architecture for V4 {
arch::maskdef!();
arch::typedef!();
fn level() -> arch::Level {
arch::Level::v4()
}
#[inline(always)]
fn run<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
unsafe { Self::run_with(self, f) }
}
#[inline(always)]
fn run_inline<F, R>(self, f: F) -> R
where
F: Target<Self, R>,
{
unsafe { Self::run_with_inline(self, f) }
}
#[inline(always)]
fn run1<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
unsafe { self.run_with_1(f, x0) }
}
#[inline(always)]
fn run1_inline<F, T0, R>(self, f: F, x0: T0) -> R
where
F: Target1<Self, R, T0>,
{
unsafe { self.run_with_1_inline(f, x0) }
}
#[inline(always)]
fn run2<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
unsafe { self.run_with_2(f, x0, x1) }
}
#[inline(always)]
fn run2_inline<F, T0, T1, R>(self, f: F, x0: T0, x1: T1) -> R
where
F: Target2<Self, R, T0, T1>,
{
unsafe { self.run_with_2_inline(f, x0, x1) }
}
#[inline(always)]
fn run3<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
unsafe { self.run_with_3(f, x0, x1, x2) }
}
#[inline(always)]
fn run3_inline<F, T0, T1, T2, R>(self, f: F, x0: T0, x1: T1, x2: T2) -> R
where
F: Target3<Self, R, T0, T1, T2>,
{
unsafe { self.run_with_3_inline(f, x0, x1, x2) }
}
fn dispatch1<F, R, T0>(self) -> Dispatched1<R, T0>
where
T0: AddLifetime,
F: for<'a> FTarget1<Self, R, T0::Of<'a>>,
{
let f: unsafe fn(Self, T0::Of<'_>) -> R = Self::run_function_with_1::<F, _, _>;
unsafe { arch::hide1(f) }
}
fn dispatch2<F, R, T0, T1>(self) -> Dispatched2<R, T0, T1>
where
T0: AddLifetime,
T1: AddLifetime,
F: for<'a, 'b> FTarget2<Self, R, T0::Of<'a>, T1::Of<'b>>,
{
let f: unsafe fn(Self, T0::Of<'_>, T1::Of<'_>) -> R =
Self::run_function_with_2::<F, _, _, _>;
unsafe { arch::hide2(f) }
}
fn dispatch3<F, R, T0, T1, T2>(self) -> Dispatched3<R, T0, T1, T2>
where
T0: AddLifetime,
T1: AddLifetime,
T2: AddLifetime,
F: for<'a, 'b, 'c> FTarget3<Self, R, T0::Of<'a>, T1::Of<'b>, T2::Of<'c>>,
{
let f: unsafe fn(Self, T0::Of<'_>, T1::Of<'_>, T2::Of<'_>) -> R =
Self::run_function_with_3::<F, _, _, _, _>;
unsafe { arch::hide3(f) }
}
}
impl From<V4> for Scalar {
fn from(_: V4) -> Scalar {
Scalar
}
}
impl From<V4> for V3 {
fn from(arch: V4) -> V3 {
arch.retarget()
}
}