use core::ptr;
use super::*;
pub struct AVX(());
impl Feature<FeatureGroup> for AVX {
fn get_support(runtime: &RuntimeSupport) -> Option<Self> {
runtime.avx().then_some(Self(()))
}
}
impl<FS> Use<FS>
where FS: HasFeature<FeatureGroup, AVX> {
defn_simd_shared!("avx", { simd_set_first(value) }, {
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi32_si128")]
pub fn set_first_u32x8(value: u32) -> u32x8;
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi32_si128")]
pub fn set_first_s32x8(value: i32) -> s32x8;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi64_si128", "_mm_cvtsi64x_si128")]
#[cfg(target_arch = "x86_64")]
pub fn set_first_u64x4(value: u64) -> u64x4;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi64_si128", "_mm_cvtsi64x_si128")]
#[cfg(target_arch = "x86_64")]
pub fn set_first_s64x4(value: i64) -> s64x4;
});
defn_simd_shared!("avx", fn(T) -> R {
simd_shuffle(value, T::splat(0), const {
simd_slice_indices::<R>(0)
})
}, {
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_u8x16x2(value: u8x16) -> u8x32;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_u16x8x2(value: u16x8) -> u16x16;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_u32x4x2(value: u32x4) -> u32x8;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_u64x2x2(value: u64x2) -> u64x4;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_s8x16x2(value: s8x16) -> s8x32;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_s16x8x2(value: s16x8) -> s16x16;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_s32x4x2(value: s32x4) -> s32x8;
#[intel_equivalents("_mm256_castsi128_si256", "_mm256_zextsi128_si256")]
pub fn set_first_s64x2x2(value: s64x2) -> s64x4;
});
defn_simd_shared!("avx", { simd_extract(x, 0) }, {
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm256_cvtsi256_si32", "_mm_cvtsi128_si32")]
pub fn get_first_u32x8(x: u32x8) -> u32;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi128_si64", "_mm_cvtsi128_si64x")]
#[cfg(target_arch = "x86_64")]
pub fn get_first_u64x4(x: u64x4) -> u64;
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm256_cvtsi256_si32", "_mm_cvtsi128_si32")]
pub fn get_first_s32x8(x: s32x8) -> i32;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi128_si64", "_mm_cvtsi128_si64x")]
#[cfg(target_arch = "x86_64")]
pub fn get_first_s64x4(x: s64x4) -> i64;
});
defn_simd_shared!("avx", fn(T) -> R {
simd_shuffle(value, T::splat(0), const {
simd_slice_indices::<R>(0)
})
}, {
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_u8x16x2(value: u8x32) -> u8x16;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_u16x8x2(value: u16x16) -> u16x8;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_u32x4x2(value: u32x8) -> u32x4;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_u64x2x2(value: u64x4) -> u64x2;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_s8x16x2(value: s8x32) -> s8x16;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_s16x8x2(value: s16x16) -> s16x8;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_s32x4x2(value: s32x8) -> s32x4;
#[intel_equivalents("_mm256_castsi256_si128")]
pub fn get_first_s64x2x2(value: s64x4) -> s64x2;
});
defn_simd_shared!("avx", {
ptr::read_unaligned(ptr as *const _ as *const _)
}, {
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_u8x32(ptr: &[u8; 32]) -> u8x32;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_u16x16(ptr: &[u16; 16]) -> u16x16;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_u32x8(ptr: &[u32; 8]) -> u32x8;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_u64x4(ptr: &[u64; 4]) -> u64x4;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_s8x32(ptr: &[i8; 32]) -> s8x32;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_s16x16(ptr: &[i16; 16]) -> s16x16;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_s32x8(ptr: &[i32; 8]) -> s32x8;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_loadu_si256")]
pub fn load_s64x4(ptr: &[i64; 4]) -> s64x4;
});
defn_simd_shared!("avx", { *ptr }, {
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_u8x32(ptr: &u8x32) -> u8x32;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_u16x16(ptr: &u16x16) -> u16x16;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_u32x8(ptr: &u32x8) -> u32x8;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_u64x4(ptr: &u64x4) -> u64x4;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_s8x32(ptr: &s8x32) -> s8x32;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_s16x16(ptr: &s16x16) -> s16x16;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_s32x8(ptr: &s32x8) -> s32x8;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm256_load_si256")]
pub fn load_aligned_s64x4(ptr: &s64x4) -> s64x4;
});
defn_simd_shared!("avx", {
ptr::write_unaligned(ptr as *mut _ as *mut _, x)
}, {
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_u8x32(x: u8x32, ptr: &mut [u8; 32]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_u16x16(x: u16x16, ptr: &mut [u16; 16]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_u32x8(x: u32x8, ptr: &mut [u32; 8]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_u64x4(x: u64x4, ptr: &mut [u64; 4]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_s8x32(x: s8x32, ptr: &mut [i8; 32]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_s16x16(x: s16x16, ptr: &mut [i16; 16]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_s32x8(x: s32x8, ptr: &mut [i32; 8]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_s64x4(x: s64x4, ptr: &mut [i64; 4]);
});
defn_simd_shared!("avx", { *ptr = x }, {
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_u8x32(x: u8x32, ptr: &mut u8x32);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_u16x16(x: u16x16, ptr: &mut u16x16);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_u32x8(x: u32x8, ptr: &mut u32x8);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_u64x4(x: u64x4, ptr: &mut u64x4);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_s8x32(x: s8x32, ptr: &mut s8x32);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_s16x16(x: s16x16, ptr: &mut s16x16);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_s32x8(x: s32x8, ptr: &mut s32x8);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm256_storeu_si256")]
pub fn store_aligned_s64x4(x: s64x4, ptr: &mut s64x4);
});
}
impl<FS> Use<FS>
where FS: HasFeature<FeatureGroup, AVX> {
defn_simd_shared!("avx", { simd_set_first(value) }, {
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi32_si128")]
pub fn set_first_u32x4(value: u32) -> u32x4;
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi32_si128")]
pub fn set_first_s32x4(value: i32) -> s32x4;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi64_si128", "_mm_cvtsi64x_si128")]
#[cfg(target_arch = "x86_64")]
pub fn set_first_u64x2(value: u64) -> u64x2;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi64_si128", "_mm_cvtsi64x_si128")]
#[cfg(target_arch = "x86_64")]
pub fn set_first_s64x2(value: i64) -> s64x2;
});
defn_simd_shared!("avx", { simd_extract(x, 0) }, {
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi128_si32")]
pub fn get_first_u32x4(x: u32x4) -> u32;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi128_si64", "_mm_cvtsi128_si64x")]
pub fn get_first_u64x2(x: u64x2) -> u64;
#[intrinsic_for("vmovd")]
#[intel_equivalents("_mm_cvtsi128_si32")]
pub fn get_first_s32x4(x: s32x4) -> i32;
#[intrinsic_for("vmovq")]
#[intel_equivalents("_mm_cvtsi128_si64", "_mm_cvtsi128_si64x")]
pub fn get_first_s64x2(x: s64x2) -> i64;
});
defn_simd_shared!("avx", fn(T, E) -> R {
const_assert!(INDEX < T::LEN as u8);
simd_insert(x, const { INDEX as u32 }, e)
}, {
#[intrinsic_for("vpinsrw")]
#[intel_equivalents("_mm_insert_epi16")]
pub fn put_u16x8<INDEX: u8>(x: u16x8, e: u16) -> u16x8;
#[intrinsic_for("vpinsrw")]
#[intel_equivalents("_mm_insert_epi16")]
pub fn put_s16x8<INDEX: u8>(x: s16x8, e: i16) -> s16x8;
});
defn_simd_shared!("avx", fn(T) -> E {
const_assert!(INDEX < T::LEN as u8);
simd_extract(x, const { INDEX as u32 })
}, {
#[intrinsic_for("vpextrw")]
#[intel_equivalents("_mm_extract_epi16")]
pub fn get_u16x8<INDEX: u8>(x: u16x8) -> u16;
#[intrinsic_for("vpextrw")]
#[intel_equivalents("_mm_extract_epi16")]
pub fn get_s16x8<INDEX: u8>(x: s16x8) -> i16;
});
defn_simd_shared!("avx", {
ptr::read_unaligned(ptr as *const _ as *const _)
}, {
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_u8x16(ptr: &[u8; 16]) -> u8x16;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_u16x8(ptr: &[u16; 8]) -> u16x8;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_u32x4(ptr: &[u32; 4]) -> u32x4;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_u64x2(ptr: &[u64; 2]) -> u64x2;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_s8x16(ptr: &[i8; 16]) -> s8x16;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_s16x8(ptr: &[i16; 8]) -> s16x8;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_s32x4(ptr: &[i32; 4]) -> s32x4;
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_loadu_si128")]
pub fn load_s64x2(ptr: &[i64; 2]) -> s64x2;
});
defn_simd_shared!("avx", { *ptr }, {
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_u8x16(ptr: &u8x16) -> u8x16;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_u16x8(ptr: &u16x8) -> u16x8;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_u32x4(ptr: &u32x4) -> u32x4;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_u64x2(ptr: &u64x2) -> u64x2;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_s8x16(ptr: &s8x16) -> s8x16;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_s16x8(ptr: &s16x8) -> s16x8;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_s32x4(ptr: &s32x4) -> s32x4;
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_load_si128")]
pub fn load_aligned_s64x2(ptr: &s64x2) -> s64x2;
});
defn_simd_shared!("avx", {
ptr::write_unaligned(ptr as *mut _ as *mut _, x)
}, {
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_u8x16(x: u8x16, ptr: &mut [u8; 16]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_u16x8(x: u16x8, ptr: &mut [u16; 8]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_u32x4(x: u32x4, ptr: &mut [u32; 4]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_u64x2(x: u64x2, ptr: &mut [u64; 2]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_s8x16(x: s8x16, ptr: &mut [i8; 16]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_s16x8(x: s16x8, ptr: &mut [i16; 8]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_s32x4(x: s32x4, ptr: &mut [i32; 4]);
#[intrinsic_for("vmovdqu")]
#[intel_equivalents("_mm_storeu_si128")]
pub fn store_s64x2(x: s64x2, ptr: &mut [i64; 2]);
});
defn_simd_shared!("avx", { *ptr = x }, {
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_u8x16(x: u8x16, ptr: &mut u8x16);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_u16x8(x: u16x8, ptr: &mut u16x8);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_u32x4(x: u32x4, ptr: &mut u32x4);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_u64x2(x: u64x2, ptr: &mut u64x2);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_s8x16(x: s8x16, ptr: &mut s8x16);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_s16x8(x: s16x8, ptr: &mut s16x8);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_s32x4(x: s32x4, ptr: &mut s32x4);
#[intrinsic_for("vmovdqa")]
#[intel_equivalents("_mm_store_si128")]
pub fn store_aligned_s64x2(x: s64x2, ptr: &mut s64x2);
});
defn_simd_shared!("avx", { simd_add(a, b) }, {
#[intrinsic_for("vpaddb")]
#[intel_equivalents("_mm_add_epi8")]
pub fn add_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpaddw")]
#[intel_equivalents("_mm_add_epi16")]
pub fn add_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpaddd")]
#[intel_equivalents("_mm_add_epi32")]
pub fn add_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpaddq")]
#[intel_equivalents("_mm_add_epi64")]
pub fn add_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpaddb")]
#[intel_equivalents("_mm_add_epi8")]
pub fn add_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpaddw")]
#[intel_equivalents("_mm_add_epi16")]
pub fn add_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpaddd")]
#[intel_equivalents("_mm_add_epi32")]
pub fn add_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpaddq")]
#[intel_equivalents("_mm_add_epi64")]
pub fn add_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", { simd_sub(a, b) }, {
#[intrinsic_for("vpsubb")]
#[intel_equivalents("_mm_sub_epi8")]
pub fn sub_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpsubw")]
#[intel_equivalents("_mm_sub_epi16")]
pub fn sub_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpsubd")]
#[intel_equivalents("_mm_sub_epi32")]
pub fn sub_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpsubq")]
#[intel_equivalents("_mm_sub_epi64")]
pub fn sub_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpsubb")]
#[intel_equivalents("_mm_sub_epi8")]
pub fn sub_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpsubw")]
#[intel_equivalents("_mm_sub_epi16")]
pub fn sub_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpsubd")]
#[intel_equivalents("_mm_sub_epi32")]
pub fn sub_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpsubq")]
#[intel_equivalents("_mm_sub_epi64")]
pub fn sub_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", { simd_saturating_add(a, b) }, {
#[intrinsic_for("vpaddsb")]
#[intel_equivalents("_mm_adds_epi8")]
pub fn saturating_add_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpaddsw")]
#[intel_equivalents("_mm_adds_epi16")]
pub fn saturating_add_s16x8(a: s16x8, b: s16x8) -> s16x8;
});
defn_simd_shared!("avx", { simd_saturating_sub(a, b) }, {
#[intrinsic_for("vpsubsb")]
#[intel_equivalents("_mm_subs_epi8")]
pub fn saturating_sub_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpsubsw")]
#[intel_equivalents("_mm_subs_epi16")]
pub fn saturating_sub_s16x8(a: s16x8, b: s16x8) -> s16x8;
});
defn_simd_shared!("avx", { simd_mul(a, b) }, {
#[intrinsic_for("vpmullw")]
#[intel_equivalents("_mm_mullo_epi16")]
pub fn mul_lo_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpmullw")]
#[intel_equivalents("_mm_mullo_epi16")]
pub fn mul_lo_s16x8(a: s16x8, b: s16x8) -> s16x8;
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmulhuw")]
#[intel_equivalents("_mm_mulhi_epu16")]
pub fn mul_hi_u16x8(a: u16x8, b: u16x8) -> u16x8 {
let prod = simd_mul(simd_cast(a), simd_cast(b));
simd_cast(simd_shr(prod, u32x8::splat(16)))
}
#[intrinsic_for("vpmulhw")]
#[intel_equivalents("_mm_mulhi_epi16")]
pub fn mul_hi_s16x8(a: s16x8, b: s16x8) -> s16x8 {
let prod = simd_mul(simd_cast(a), simd_cast(b));
simd_cast(simd_shr(prod, s32x8::splat(16)))
}
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmuludq")]
#[intel_equivalents("_mm_mul_epu32")]
pub fn mul_u32_u64x2(a: u64x2, b: u64x2) -> u64x2 {
let [a, b]: [u32x2; 2] = [simd_cast(a), simd_cast(b)];
simd_mul(simd_cast(a), simd_cast(b))
}
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpmaddwd")]
#[intel_equivalents("_mm_madd_epi16")]
pub fn sum_of_prod_s16x2x4
(x: s16x8, y: s16x8) -> s32x4
= "llvm.x86.sse2.pmadd.wd";
});
defn_simd_shared!("avx", { simd_eq(a, b) }, {
#[intrinsic_for("vpcmpeqb")]
#[intel_equivalents("_mm_cmpeq_epi8")]
pub fn cmp_eq_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpcmpeqw")]
#[intel_equivalents("_mm_cmpeq_epi16")]
pub fn cmp_eq_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpcmpeqd")]
#[intel_equivalents("_mm_cmpeq_epi32")]
pub fn cmp_eq_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpcmpeqb")]
#[intel_equivalents("_mm_cmpeq_epi8")]
pub fn cmp_eq_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpcmpeqw")]
#[intel_equivalents("_mm_cmpeq_epi16")]
pub fn cmp_eq_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpcmpeqd")]
#[intel_equivalents("_mm_cmpeq_epi32")]
pub fn cmp_eq_s32x4(a: s32x4, b: s32x4) -> s32x4;
});
defn_simd_shared!("avx", { simd_gt(a, b) }, {
#[intrinsic_for("vpcmpgtb")]
#[intel_equivalents("_mm_cmpgt_epi8", "_mm_cmplt_epi8")]
pub fn cmp_gt_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpcmpgtw")]
#[intel_equivalents("_mm_cmpgt_epi16", "_mm_cmplt_epi16")]
pub fn cmp_gt_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpcmpgtd")]
#[intel_equivalents("_mm_cmpgt_epi32", "_mm_cmplt_epi32")]
pub fn cmp_gt_s32x4(a: s32x4, b: s32x4) -> s32x4;
});
defn_simd_shared!("avx", { simd_and(a, b) }, {
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpand")]
#[intel_equivalents("_mm_and_si128")]
pub fn and_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", { simd_or(a, b) }, {
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpor")]
#[intel_equivalents("_mm_or_si128")]
pub fn ior_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", { simd_xor(a, b) }, {
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpxor")]
#[intel_equivalents("_mm_xor_si128")]
pub fn xor_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", { simd_andnot(a, b) }, {
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpandn")]
#[intel_equivalents("_mm_andnot_si128")]
pub fn and_not_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpavgb")]
#[intel_equivalents("_mm_avg_epu8")]
pub fn avg_u8x16(a: u8x16, b: u8x16) -> u8x16
= simd_avg::<u8x16, u16x16>;
#[intrinsic_for("vpavgw")]
#[intel_equivalents("_mm_avg_epu16")]
pub fn avg_u16x8(a: u16x8, b: u16x8) -> u16x8
= simd_avg::<u16x8, u32x8>;
});
defn_simd_shared!("avx", { simd_max(a, b) }, {
#[intrinsic_for("vpmaxub")]
#[intel_equivalents("_mm_max_epu8")]
pub fn max_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpmaxsw")]
#[intel_equivalents("_mm_max_epi16")]
pub fn max_s16x8(a: s16x8, b: s16x8) -> s16x8;
});
defn_simd_shared!("avx", { simd_min(a, b) }, {
#[intrinsic_for("vpminub")]
#[intel_equivalents("_mm_min_epu8")]
pub fn min_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpminsw")]
#[intel_equivalents("_mm_min_epi16")]
pub fn min_s16x8(a: s16x8, b: s16x8) -> s16x8;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpsllw")]
#[intel_equivalents("_mm_sll_epi16")]
pub fn shl_all_u16x8(x: u16x8, s: u64x2) -> u16x8
= "llvm.x86.sse2.psll.w";
#[intrinsic_for("vpslld")]
#[intel_equivalents("_mm_sll_epi32")]
pub fn shl_all_u32x4(x: u32x4, s: u64x2) -> u32x4
= "llvm.x86.sse2.psll.d";
#[intrinsic_for("vpsllq")]
#[intel_equivalents("_mm_sll_epi64")]
pub fn shl_all_u64x2(x: u64x2, s: u64x2) -> u64x2
= "llvm.x86.sse2.psll.q";
#[intrinsic_for("vpsllw")]
#[intel_equivalents("_mm_sll_epi16")]
pub fn shl_all_s16x8(x: s16x8, s: u64x2) -> s16x8
= "llvm.x86.sse2.psll.w";
#[intrinsic_for("vpslld")]
#[intel_equivalents("_mm_sll_epi32")]
pub fn shl_all_s32x4(x: s32x4, s: u64x2) -> s32x4
= "llvm.x86.sse2.psll.d";
#[intrinsic_for("vpsllq")]
#[intel_equivalents("_mm_sll_epi64")]
pub fn shl_all_s64x2(x: s64x2, s: u64x2) -> s64x2
= "llvm.x86.sse2.psll.q";
});
defn_simd_shared!("avx", { simd_shl_all::<_, BITS>(x) }, {
#[intrinsic_for("vpsllw")]
#[intel_equivalents("_mm_slli_epi16")]
pub fn shl_all_by_u16x8<BITS: u8>(x: u16x8) -> u16x8;
#[intrinsic_for("vpslld")]
#[intel_equivalents("_mm_slli_epi32")]
pub fn shl_all_by_u32x4<BITS: u8>(x: u32x4) -> u32x4;
#[intrinsic_for("vpsllq")]
#[intel_equivalents("_mm_slli_epi64")]
pub fn shl_all_by_u64x2<BITS: u8>(x: u64x2) -> u64x2;
#[intrinsic_for("vpsllw")]
#[intel_equivalents("_mm_slli_epi16")]
pub fn shl_all_by_s16x8<BITS: u8>(x: s16x8) -> s16x8;
#[intrinsic_for("vpslld")]
#[intel_equivalents("_mm_slli_epi32")]
pub fn shl_all_by_s32x4<BITS: u8>(x: s32x4) -> s32x4;
#[intrinsic_for("vpsllq")]
#[intel_equivalents("_mm_slli_epi64")]
pub fn shl_all_by_s64x2<BITS: u8>(x: s64x2) -> s64x2;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpsrlw")]
#[intel_equivalents("_mm_srl_epi16")]
pub fn shr_all_u16x8(x: u16x8, s: u64x2) -> u16x8
= "llvm.x86.sse2.psrl.w";
#[intrinsic_for("vpsrld")]
#[intel_equivalents("_mm_srl_epi32")]
pub fn shr_all_u32x4(x: u32x4, s: u64x2) -> u32x4
= "llvm.x86.sse2.psrl.d";
#[intrinsic_for("vpsrlq")]
#[intel_equivalents("_mm_srl_epi64")]
pub fn shr_all_u64x2(x: u64x2, s: u64x2) -> u64x2
= "llvm.x86.sse2.psrl.q";
#[intrinsic_for("vpsraw")]
#[intel_equivalents("_mm_sra_epi16")]
pub fn shr_all_s16x8(x: s16x8, s: u64x2) -> s16x8
= "llvm.x86.sse2.psra.w";
#[intrinsic_for("vpsrad")]
#[intel_equivalents("_mm_sra_epi32")]
pub fn shr_all_s32x4(x: s32x4, s: u64x2) -> s32x4
= "llvm.x86.sse2.psra.d";
});
defn_simd_shared!("avx", { simd_shr_all::<_, BITS>(x) }, {
#[intrinsic_for("vpsrlw")]
#[intel_equivalents("_mm_srli_epi16")]
pub fn shr_all_by_u16x8<BITS: u8>(x: u16x8) -> u16x8;
#[intrinsic_for("vpsrld")]
#[intel_equivalents("_mm_srli_epi32")]
pub fn shr_all_by_u32x4<BITS: u8>(x: u32x4) -> u32x4;
#[intrinsic_for("vpsrlq")]
#[intel_equivalents("_mm_srli_epi64")]
pub fn shr_all_by_u64x2<BITS: u8>(x: u64x2) -> u64x2;
#[intrinsic_for("vpsraw")]
#[intel_equivalents("_mm_srai_epi16")]
pub fn shr_all_by_s16x8<BITS: u8>(x: s16x8) -> s16x8;
#[intrinsic_for("vpsrad")]
#[intel_equivalents("_mm_srai_epi32")]
pub fn shr_all_by_s32x4<BITS: u8>(x: s32x4) -> s32x4;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpackuswb")]
#[intel_equivalents("_mm_packus_epi16")]
pub fn concat_and_saturate_u8_s16x8(a: s16x8, b: s16x8) -> u8x16
= "llvm.x86.sse2.packuswb.128";
#[intrinsic_for("vpacksswb")]
#[intel_equivalents("_mm_packs_epi16")]
pub fn concat_and_saturate_s8_s16x8(a: s16x8, b: s16x8) -> s8x16
= "llvm.x86.sse2.packsswb.128";
#[intrinsic_for("vpackssdw")]
#[intel_equivalents("_mm_packs_epi32")]
pub fn concat_and_saturate_s16_s32x4(a: s32x4, b: s32x4) -> s16x8
= "llvm.x86.sse2.packssdw.128";
});
defn_simd_shared!("avx", fn(T, U) -> R {
simd_shuffle(a, b, const { simd_unpack_indices::<R>(0) })
}, {
#[intrinsic_for("vpunpcklbw")]
#[intel_equivalents("_mm_unpacklo_epi8")]
pub fn interleave_lo_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpunpcklwd")]
#[intel_equivalents("_mm_unpacklo_epi16")]
pub fn interleave_lo_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpunpckldq")]
#[intel_equivalents("_mm_unpacklo_epi32")]
pub fn interleave_lo_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpunpcklqdq")]
#[intel_equivalents("_mm_unpacklo_epi64")]
pub fn interleave_lo_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpunpcklbw")]
#[intel_equivalents("_mm_unpacklo_epi8")]
pub fn interleave_lo_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpunpcklwd")]
#[intel_equivalents("_mm_unpacklo_epi16")]
pub fn interleave_lo_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpunpckldq")]
#[intel_equivalents("_mm_unpacklo_epi32")]
pub fn interleave_lo_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpunpcklqdq")]
#[intel_equivalents("_mm_unpacklo_epi64")]
pub fn interleave_lo_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_shared!("avx", fn(T, U) -> R {
simd_shuffle(a, b, const { simd_unpack_indices::<R>(T::LEN / 2) })
}, {
#[intrinsic_for("vpunpckhbw")]
#[intel_equivalents("_mm_unpackhi_epi8")]
pub fn interleave_hi_u8x16(a: u8x16, b: u8x16) -> u8x16;
#[intrinsic_for("vpunpckhwd")]
#[intel_equivalents("_mm_unpackhi_epi16")]
pub fn interleave_hi_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpunpckhdq")]
#[intel_equivalents("_mm_unpackhi_epi32")]
pub fn interleave_hi_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpunpckhqdq")]
#[intel_equivalents("_mm_unpackhi_epi64")]
pub fn interleave_hi_u64x2(a: u64x2, b: u64x2) -> u64x2;
#[intrinsic_for("vpunpckhbw")]
#[intel_equivalents("_mm_unpackhi_epi8")]
pub fn interleave_hi_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpunpckhwd")]
#[intel_equivalents("_mm_unpackhi_epi16")]
pub fn interleave_hi_s16x8(a: s16x8, b: s16x8) -> s16x8;
#[intrinsic_for("vpunpckhdq")]
#[intel_equivalents("_mm_unpackhi_epi32")]
pub fn interleave_hi_s32x4(a: s32x4, b: s32x4) -> s32x4;
#[intrinsic_for("vpunpckhqdq")]
#[intel_equivalents("_mm_unpackhi_epi64")]
pub fn interleave_hi_s64x2(a: s64x2, b: s64x2) -> s64x2;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpsadbw")]
#[intel_equivalents("_mm_sad_epu8")]
pub fn sum_of_abs_diff_u8x16(a: u8x16, b: u8x16) -> u64x2
= "llvm.x86.sse2.psad.bw";
});
defn_simd_shared!("avx", fn(T) -> R {
const_assert!(ELEMS < 16);
simd_shuffle(T::splat(0), x, const {
simd_slice_indices::<T>(T::LEN - (ELEMS as usize))
})
}, {
#[intrinsic_for("vpslldq")]
#[intel_equivalents("_mm_bslli_si128", "_mm_slli_si128")]
pub fn move_l_by_u8x16<ELEMS: u8>(x: u8x16) -> u8x16;
#[intrinsic_for("vpslldq")]
#[intel_equivalents("_mm_bslli_si128", "_mm_slli_si128")]
pub fn move_l_by_s8x16<ELEMS: u8>(x: s8x16) -> s8x16;
});
defn_simd_shared!("avx", fn(T) -> R {
const_assert!(ELEMS < 16);
simd_shuffle(T::splat(0), x, const {
simd_slice_indices::<T>(ELEMS as usize)
})
}, {
#[intrinsic_for("vpsrldq")]
#[intel_equivalents("_mm_bsrli_si128", "_mm_srli_si128")]
pub fn move_r_by_u8x16<ELEMS: u8>(x: u8x16) -> u8x16;
#[intrinsic_for("vpsrldq")]
#[intel_equivalents("_mm_bsrli_si128", "_mm_srli_si128")]
pub fn move_r_by_s8x16<ELEMS: u8>(x: s8x16) -> s8x16;
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmovmskb")]
#[intel_equivalents("_mm_movemask_epi8")]
pub fn bitmask_u8x16(x: u8x16) -> u16 {
simd_bitmask(simd_ge::<_, u8x16>(x, u8x16::splat(0x80)))
}
#[intrinsic_for("vpmovmskb")]
#[intel_equivalents("_mm_movemask_epi8")]
pub fn bitmask_s8x16(x: s8x16) -> u16 {
simd_bitmask(simd_lt::<_, s8x16>(x, s8x16::splat(0)))
}
});
}
impl<FS> Use<FS>
where FS: HasFeature<FeatureGroup, AVX> {
defn_simd_shared!("avx", { simd_abs(x) }, {
#[intrinsic_for("vpabsb")]
#[intel_equivalents("_mm_abs_epi8")]
pub fn abs_s8x16(x: s8x16) -> s8x16;
#[intrinsic_for("vpabsw")]
#[intel_equivalents("_mm_abs_epi16")]
pub fn abs_s16x8(x: s16x8) -> s16x8;
#[intrinsic_for("vpabsd")]
#[intel_equivalents("_mm_abs_epi32")]
pub fn abs_s32x4(x: s32x4) -> s32x4;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vphaddw")]
#[intel_equivalents("_mm_hadd_epi16")]
pub fn concat_and_reduce_add_u16x2x4(x: u16x8, y: u16x8) -> u16x8
= "llvm.x86.ssse3.phadd.w.128";
#[intrinsic_for("vphaddd")]
#[intel_equivalents("_mm_hadd_epi32")]
pub fn concat_and_reduce_add_u32x2x2(x: u32x4, y: u32x4) -> u32x4
= "llvm.x86.ssse3.phadd.d.128";
#[intrinsic_for("vphaddw")]
#[intel_equivalents("_mm_hadd_epi16")]
pub fn concat_and_reduce_add_s16x2x4(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.phadd.w.128";
#[intrinsic_for("vphaddd")]
#[intel_equivalents("_mm_hadd_epi32")]
pub fn concat_and_reduce_add_s32x2x2(x: s32x4, y: s32x4) -> s32x4
= "llvm.x86.ssse3.phadd.d.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vphaddsw")]
#[intel_equivalents("_mm_hadds_epi16")]
pub fn concat_and_reduce_saturating_add_s16x2x4
(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.phadd.sw.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vphsubw")]
#[intel_equivalents("_mm_hsub_epi16")]
pub fn concat_and_reduce_sub_u16x2x4(x: u16x8, y: u16x8) -> u16x8
= "llvm.x86.ssse3.phsub.w.128";
#[intrinsic_for("vphsubd")]
#[intel_equivalents("_mm_hsub_epi32")]
pub fn concat_and_reduce_sub_u32x2x2(x: u32x4, y: u32x4) -> u32x4
= "llvm.x86.ssse3.phsub.d.128";
#[intrinsic_for("vphsubw")]
#[intel_equivalents("_mm_hsub_epi16")]
pub fn concat_and_reduce_sub_s16x2x4(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.phsub.w.128";
#[intrinsic_for("vphsubd")]
#[intel_equivalents("_mm_hsub_epi32")]
pub fn concat_and_reduce_sub_s32x2x2(x: s32x4, y: s32x4) -> s32x4
= "llvm.x86.ssse3.phsub.d.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vphsubsw")]
#[intel_equivalents("_mm_hsubs_epi16")]
pub fn concat_and_reduce_saturating_sub_s16x2x4
(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.phsub.sw.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpmaddubsw")]
#[intel_equivalents("_mm_maddubs_epi16")]
pub fn sum_of_prod_u8x2x8
(x: u16x8, y: u16x8) -> s16x8
= "llvm.x86.ssse3.pmadd.ub.sw.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpmulhrsw")]
#[intel_equivalents("_mm_mulhrs_epi16")]
pub fn mul_and_halve_s16x8
(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.pmul.hr.sw.128";
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpsignb")]
#[intel_equivalents("_mm_sign_epi8")]
pub fn mul_sign_s8x16(x: s8x16, y: s8x16) -> s8x16
= "llvm.x86.ssse3.psign.b.128";
#[intrinsic_for("vpsignw")]
#[intel_equivalents("_mm_sign_epi16")]
pub fn mul_sign_s16x8(x: s16x8, y: s16x8) -> s16x8
= "llvm.x86.ssse3.psign.w.128";
#[intrinsic_for("vpsignd")]
#[intel_equivalents("_mm_sign_epi32")]
pub fn mul_sign_s32x4(x: s32x4, y: s32x4) -> s32x4
= "llvm.x86.ssse3.psign.d.128";
});
defn_simd_shared!("avx", fn(T, U) -> R {
const_assert!(SHIFT < 16);
simd_shuffle(x, y, const {
simd_slice_indices::<R>(SHIFT as usize)
})
}, {
#[intrinsic_for("vpalignr")]
#[intel_equivalents("_mm_alignr_epi8")]
pub fn align_elems_by_u8x16<SHIFT: u8>(x: u8x16, y: u8x16) -> u8x16;
#[intrinsic_for("vpalignr")]
#[intel_equivalents("_mm_alignr_epi8")]
pub fn align_elems_by_s8x16<SHIFT: u8>(x: s8x16, y: s8x16) -> s8x16;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpshufb")]
#[intel_equivalents("_mm_shuffle_epi8")]
pub fn shuffle_u8x16(x: u8x16, idxs: s8x16) -> u8x16
= "llvm.x86.ssse3.pshuf.b.128";
#[intrinsic_for("vpshufb")]
#[intel_equivalents("_mm_shuffle_epi8")]
pub fn shuffle_s8x16(x: s8x16, idxs: s8x16) -> s8x16
= "llvm.x86.ssse3.pshuf.b.128";
});
}
impl<FS> Use<FS>
where FS: HasFeature<FeatureGroup, AVX> {
defn_simd_shared!("avx", {
simd_select_bitmask(MASK, y, x)
}, {
#[intrinsic_for("vpblendw")]
#[intel_equivalents("_mm_blend_epi16")]
pub fn blend_by_u16x8<MASK: u8>(x: u16x8, y: u16x8) -> u16x8;
#[intrinsic_for("vpblendw")]
#[intel_equivalents("_mm_blend_epi16")]
pub fn blend_by_s16x8<MASK: u8>(x: s16x8, y: s16x8) -> s16x8;
});
defn_simd_shared!("avx", fn(T, U, M) -> R {
let mask: M = simd_lt(mask, M::splat(0));
simd_select(mask, y, x)
}, {
#[intrinsic_for("vpblendvb")]
#[intel_equivalents("_mm_blendv_epi8")]
pub fn blend_u8x16(x: u8x16, y: u8x16, mask: s8x16) -> u8x16;
#[intrinsic_for("vpblendvb")]
#[intel_equivalents("_mm_blendv_epi8")]
pub fn blend_s8x16(x: s8x16, y: s8x16, mask: s8x16) -> s8x16;
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmuldq")]
#[intel_equivalents("_mm_mul_epi32")]
pub fn mul_s32_s64x2(a: s64x2, b: s64x2) -> s64x2 {
let [a, b]: [s32x2; 2] = [simd_cast(a), simd_cast(b)];
simd_mul(simd_cast(a), simd_cast(b))
}
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmulld")]
#[intel_equivalents("_mm_mullo_epi32")]
pub fn mul_lo_s32x4(a: s32x4, b: s32x4) -> s32x4 {
simd_mul(a, b)
}
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpcmpeqq")]
#[intel_equivalents("_mm_cmpeq_epi64")]
pub fn cmp_eq_u64x2(a: u64x2, b: u64x2) -> u64x2 = simd_eq;
#[intrinsic_for("vpcmpeqq")]
#[intel_equivalents("_mm_cmpeq_epi64")]
pub fn cmp_eq_s64x2(a: s64x2, b: s64x2) -> s64x2 = simd_eq;
});
defn_simd_shared!("avx", { simd_max(a, b) }, {
#[intrinsic_for("vpmaxuw")]
#[intel_equivalents("_mm_max_epu16")]
pub fn max_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpmaxud")]
#[intel_equivalents("_mm_max_epu32")]
pub fn max_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpmaxsb")]
#[intel_equivalents("_mm_max_epi8")]
pub fn max_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpmaxsd")]
#[intel_equivalents("_mm_max_epi32")]
pub fn max_s32x4(a: s32x4, b: s32x4) -> s32x4;
});
defn_simd_shared!("avx", { simd_min(a, b) }, {
#[intrinsic_for("vpminuw")]
#[intel_equivalents("_mm_min_epu16")]
pub fn min_u16x8(a: u16x8, b: u16x8) -> u16x8;
#[intrinsic_for("vpminud")]
#[intel_equivalents("_mm_min_epu32")]
pub fn min_u32x4(a: u32x4, b: u32x4) -> u32x4;
#[intrinsic_for("vpminsb")]
#[intel_equivalents("_mm_min_epi8")]
pub fn min_s8x16(a: s8x16, b: s8x16) -> s8x16;
#[intrinsic_for("vpminsd")]
#[intel_equivalents("_mm_min_epi32")]
pub fn min_s32x4(a: s32x4, b: s32x4) -> s32x4;
});
defn_simd_manual!("avx", {
#[intrinsic_for("vpmovzxbw")]
#[intel_equivalents("_mm_cvtepu8_epi16")]
pub fn expand_u8x16_u16x8(x: u8x16) -> u16x8
= simd_expand::<_, u8x8, _>;
#[intrinsic_for("vpmovzxbw")]
#[intel_equivalents("_mm_cvtepu8_epi16")]
pub fn expand_u8x16_s16x8(x: u8x16) -> s16x8
= simd_expand::<_, u8x8, _>;
#[intrinsic_for("vpmovzxbd")]
#[intel_equivalents("_mm_cvtepu8_epi32")]
pub fn expand_u8x16_u32x4(x: u8x16) -> u32x4
= simd_expand::<_, u8x4, _>;
#[intrinsic_for("vpmovzxbd")]
#[intel_equivalents("_mm_cvtepu8_epi32")]
pub fn expand_u8x16_s32x4(x: u8x16) -> s32x4
= simd_expand::<_, u8x4, _>;
#[intrinsic_for("vpmovzxbq")]
#[intel_equivalents("_mm_cvtepu8_epi64")]
pub fn expand_u8x16_u64x2(x: u8x16) -> u64x2
= simd_expand::<_, u8x2, _>;
#[intrinsic_for("vpmovzxbq")]
#[intel_equivalents("_mm_cvtepu8_epi64")]
pub fn expand_u8x16_s64x2(x: u8x16) -> s64x2
= simd_expand::<_, u8x2, _>;
#[intrinsic_for("vpmovzxwd")]
#[intel_equivalents("_mm_cvtepu16_epi32")]
pub fn expand_u16x8_u32x4(x: u16x8) -> u32x4
= simd_expand::<_, u16x4, _>;
#[intrinsic_for("vpmovzxwd")]
#[intel_equivalents("_mm_cvtepu16_epi32")]
pub fn expand_u16x8_s32x4(x: u16x8) -> s32x4
= simd_expand::<_, u16x4, _>;
#[intrinsic_for("vpmovzxwq")]
#[intel_equivalents("_mm_cvtepu16_epi64")]
pub fn expand_u16x8_u64x2(x: u16x8) -> u64x2
= simd_expand::<_, u16x2, _>;
#[intrinsic_for("vpmovzxwq")]
#[intel_equivalents("_mm_cvtepu16_epi64")]
pub fn expand_u16x8_s64x2(x: u16x8) -> s64x2
= simd_expand::<_, u16x2, _>;
#[intrinsic_for("vpmovzxdq")]
#[intel_equivalents("_mm_cvtepu32_epi64")]
pub fn expand_u32x4_u64x2(x: u32x4) -> u64x2
= simd_expand::<_, u32x2, _>;
#[intrinsic_for("vpmovzxdq")]
#[intel_equivalents("_mm_cvtepu32_epi64")]
pub fn expand_u32x4_s64x2(x: u32x4) -> s64x2
= simd_expand::<_, u32x2, _>;
#[intrinsic_for("vpmovsxbw")]
#[intel_equivalents("_mm_cvtepi8_epi16")]
pub fn expand_s8x16_s16x8(x: s8x16) -> s16x8
= simd_expand::<_, s8x8, _>;
#[intrinsic_for("vpmovsxbd")]
#[intel_equivalents("_mm_cvtepi8_epi32")]
pub fn expand_s8x16_s32x4(x: s8x16) -> s32x4
= simd_expand::<_, s8x4, _>;
#[intrinsic_for("vpmovsxbq")]
#[intel_equivalents("_mm_cvtepi8_epi64")]
pub fn expand_s8x16_s64x2(x: s8x16) -> s64x2
= simd_expand::<_, s8x2, _>;
#[intrinsic_for("vpmovsxwd")]
#[intel_equivalents("_mm_cvtepi16_epi32")]
pub fn expand_s16x8_s32x4(x: s16x8) -> s32x4
= simd_expand::<_, s16x4, _>;
#[intrinsic_for("vpmovsxwq")]
#[intel_equivalents("_mm_cvtepi16_epi64")]
pub fn expand_s16x8_s64x2(x: s16x8) -> s64x2
= simd_expand::<_, s16x2, _>;
#[intrinsic_for("vpmovsxdq")]
#[intel_equivalents("_mm_cvtepi32_epi64")]
pub fn expand_s32x4_s64x2(x: s32x4) -> s64x2
= simd_expand::<_, s32x2, _>;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vpackusdw")]
#[intel_equivalents("_mm_packus_epi32")]
pub fn concat_and_saturate_u16_s32x4(a: s32x4, b: s32x4) -> u16x8
= "llvm.x86.sse41.packusdw.128";
});
defn_simd_shared!("avx", fn(T) -> R {
const_assert!(INDEX < T::LEN as u8);
simd_extract(x, const { INDEX as u32 })
}, {
#[intrinsic_for("vpextrb")]
#[intel_equivalents("_mm_extract_epi8")]
pub fn get_u8x16<INDEX: u8>(x: u8x16) -> u8;
#[intrinsic_for("vpextrd")]
#[intel_equivalents("_mm_extract_epi32")]
pub fn get_u32x4<INDEX: u8>(x: u32x4) -> u32;
#[intrinsic_for("vpextrq")]
#[intel_equivalents("_mm_extract_epi64")]
pub fn get_u64x2<INDEX: u8>(x: u64x2) -> u64;
#[intrinsic_for("vpextrb")]
#[intel_equivalents("_mm_extract_epi8")]
pub fn get_s8x16<INDEX: u8>(x: s8x16) -> i8;
#[intrinsic_for("vpextrd")]
#[intel_equivalents("_mm_extract_epi32")]
pub fn get_s32x4<INDEX: u8>(x: s32x4) -> i32;
#[intrinsic_for("vpextrq")]
#[intel_equivalents("_mm_extract_epi64")]
pub fn get_s64x2<INDEX: u8>(x: s64x2) -> i64;
});
defn_simd_shared!("avx", fn(T, E) -> R {
const_assert!(INDEX < T::LEN as u8);
simd_insert(x, const { INDEX as u32 }, e)
}, {
#[intrinsic_for("vpinsrb")]
#[intel_equivalents("_mm_insert_epi8")]
pub fn put_u8x16<INDEX: u8>(x: u8x16, e: u8) -> u8x16;
#[intrinsic_for("vpinsrd")]
#[intel_equivalents("_mm_insert_epi32")]
pub fn put_u32x4<INDEX: u8>(x: u32x4, e: u32) -> u32x4;
#[intrinsic_for("vpinsrq")]
#[intel_equivalents("_mm_insert_epi64")]
pub fn put_u64x2<INDEX: u8>(x: u64x2, e: u64) -> u64x2;
#[intrinsic_for("vpinsrb")]
#[intel_equivalents("_mm_insert_epi8")]
pub fn put_s8x16<INDEX: u8>(x: s8x16, e: i8) -> s8x16;
#[intrinsic_for("vpinsrd")]
#[intel_equivalents("_mm_insert_epi8")]
pub fn put_s32x4<INDEX: u8>(x: s32x4, e: i32) -> s32x4;
#[intrinsic_for("vpinsrq")]
#[intel_equivalents("_mm_insert_epi64")]
pub fn put_s64x2<INDEX: u8>(x: s64x2, e: i64) -> s64x2;
});
defn_simd_llvm!("avx", {
#[intrinsic_for("vphminposw")]
#[intel_equivalents("_mm_minpos_epu16")]
pub fn min_pos_u16x8(x: u16x8) -> u16x8
= "llvm.x86.sse41.phminposw";
});
}