Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ case ${TARGET} in
;;
# Some x86_64 targets enable by default more features beyond SSE2,
# which cause some instruction assertion checks to fail.
# (This does not disable tests that need more features, they get enabled based on
# what the host actually supports.)
x86_64-*)
export RUSTFLAGS="${RUSTFLAGS} -C target-feature=-sse3"
# We want frame pointers to be consistent across targets. On the ios_macabi target
# we cannot turn them off, so let's turn them on everywhere.
# If we ever turn these off, a bunch of `limit(...)` clauses should be reduced to
# avoid tests becoming less strict!
export RUSTFLAGS="${RUSTFLAGS} -C target-feature=-sse3 -Cforce-frame-pointers=on"
;;
#Unoptimized build uses fast-isel which breaks with msa
mips-* | mipsel-*)
Expand Down
102 changes: 73 additions & 29 deletions crates/assert-instr-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ pub fn assert_instr(
};

let instr = &invoc.instr;
let not = invoc.not;
let limit = match invoc.limit {
None => quote! { None },
Some(l) => quote! { Some(#l) },
};

let name = &func.sig.ident;
let maybe_allow_deprecated = if func
.attrs
Expand Down Expand Up @@ -179,7 +185,7 @@ pub fn assert_instr(
fn #assert_name() {
#to_test

::stdarch_test::assert(#shim_name as usize, stringify!(#shim_name), #instr);
::stdarch_test::assert(#shim_name as usize, stringify!(#shim_name), #instr, &[#(#not),*], #limit);
}
};

Expand All @@ -192,51 +198,89 @@ pub fn assert_instr(

struct Invoc {
instr: String,
not: Vec<String>,
limit: Option<syn::LitInt>,
args: Vec<(syn::Ident, syn::Expr)>,
}

fn parse_instr(input: syn::parse::ParseStream<'_>) -> syn::Result<String> {
use syn::{Token, ext::IdentExt};

let mut instr = String::new();
while !input.is_empty() {
if let Ok(ident) = syn::Ident::parse_any(input) {
instr.push_str(&ident.to_string());
continue;
}
if input.parse::<Token![.]>().is_ok() {
instr.push('.');
continue;
}
if let Ok(s) = input.parse::<syn::LitStr>() {
instr.push_str(&s.value());
continue;
}
// Some other token, must be start of the next thing.
break;
}
if instr.is_empty() {
return Err(input.error("expected an instruction"));
}
Ok(instr)
}

impl syn::parse::Parse for Invoc {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
use syn::{Token, ext::IdentExt};
use syn::{Token, parenthesized};

let instr = parse_instr(input)?;
let mut not = Vec::new();
let mut limit = None;
let mut args = Vec::new();

let mut instr = String::new();
while !input.is_empty() {
if input.parse::<Token![,]>().is_ok() {
break;
// Parse the comma after the previous thing
if input.parse::<Token![,]>().is_err() {
return Err(input.error("extra tokens at end"));
}
if let Ok(ident) = syn::Ident::parse_any(input) {
instr.push_str(&ident.to_string());
continue;
// Handle trailing comma.
if input.is_empty() {
break;
}
if input.parse::<Token![.]>().is_ok() {
instr.push('.');

// This is either `not(instr)` or `limit(n)` or `arg = val`.
// We treat `not` and `limit` as a magic identifier here.

let name = input.parse::<syn::Ident>()?;

if name == "not" {
let content;
parenthesized!(content in input);
let not_instr = parse_instr(&content)?;
if !content.is_empty() {
return Err(input.error("expected just an instruction in `not(...)`"));
}
not.push(not_instr);
continue;
}
if let Ok(s) = input.parse::<syn::LitStr>() {
instr.push_str(&s.value());
if name == "limit" {
let content;
parenthesized!(content in input);
let n = content.parse::<syn::LitInt>()?;
limit = Some(n);
continue;
}
println!("{:?}", input.cursor().token_stream());
return Err(input.error("expected an instruction"));
}
if instr.is_empty() {
return Err(input.error("expected an instruction before comma"));
}
let mut args = Vec::new();
while !input.is_empty() {
let name = input.parse::<syn::Ident>()?;

input.parse::<Token![=]>()?;
let expr = input.parse::<syn::Expr>()?;
args.push((name, expr));

if input.parse::<Token![,]>().is_err() {
if !input.is_empty() {
return Err(input.error("extra tokens at end"));
}
break;
}
}
Ok(Self { instr, args })
Ok(Self {
instr,
not,
limit,
args,
})
}
}

Expand Down
8 changes: 4 additions & 4 deletions crates/core_arch/src/x86/avx2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2321,7 +2321,7 @@ pub const fn _mm256_or_si256(a: __m256i, b: __m256i) -> __m256i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi16)
#[inline]
#[target_feature(enable = "avx2")]
#[cfg_attr(test, assert_instr(vpacksswb))]
#[cfg_attr(test, assert_instr(vpacksswb, limit(5), not(vpminsw), not(vpmaxsw)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i {
unsafe { transmute(packsswb(a.as_i16x16(), b.as_i16x16())) }
Expand All @@ -2333,7 +2333,7 @@ pub fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32)
#[inline]
#[target_feature(enable = "avx2")]
#[cfg_attr(test, assert_instr(vpackssdw))]
#[cfg_attr(test, assert_instr(vpackssdw, limit(5), not(vpminsd), not(vpmaxsd)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i {
unsafe { transmute(packssdw(a.as_i32x8(), b.as_i32x8())) }
Expand All @@ -2345,7 +2345,7 @@ pub fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16)
#[inline]
#[target_feature(enable = "avx2")]
#[cfg_attr(test, assert_instr(vpackuswb))]
#[cfg_attr(test, assert_instr(vpackuswb, limit(5), not(vpminsw), not(vpmaxsw)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i {
unsafe { transmute(packuswb(a.as_i16x16(), b.as_i16x16())) }
Expand All @@ -2357,7 +2357,7 @@ pub fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi32)
#[inline]
#[target_feature(enable = "avx2")]
#[cfg_attr(test, assert_instr(vpackusdw))]
#[cfg_attr(test, assert_instr(vpackusdw, limit(5), not(vpminsd), not(vpmaxsd)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm256_packus_epi32(a: __m256i, b: __m256i) -> __m256i {
unsafe { transmute(packusdw(a.as_i32x8(), b.as_i32x8())) }
Expand Down
8 changes: 4 additions & 4 deletions crates/core_arch/src/x86/avx512bw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6522,7 +6522,7 @@ pub fn _mm_maskz_maddubs_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i {
#[inline]
#[target_feature(enable = "avx512bw")]
#[stable(feature = "stdarch_x86_avx512", since = "1.89")]
#[cfg_attr(test, assert_instr(vpackssdw))]
#[cfg_attr(test, assert_instr(vpackssdw, limit(5), not(vpminsd), not(vpmaxsd)))]
pub fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i {
unsafe { transmute(vpackssdw(a.as_i32x16(), b.as_i32x16())) }
}
Expand Down Expand Up @@ -6617,7 +6617,7 @@ pub fn _mm_maskz_packs_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i {
#[inline]
#[target_feature(enable = "avx512bw")]
#[stable(feature = "stdarch_x86_avx512", since = "1.89")]
#[cfg_attr(test, assert_instr(vpacksswb))]
#[cfg_attr(test, assert_instr(vpacksswb, limit(5), not(vpminsw), not(vpmaxsw)))]
pub fn _mm512_packs_epi16(a: __m512i, b: __m512i) -> __m512i {
unsafe { transmute(vpacksswb(a.as_i16x32(), b.as_i16x32())) }
}
Expand Down Expand Up @@ -6712,7 +6712,7 @@ pub fn _mm_maskz_packs_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i {
#[inline]
#[target_feature(enable = "avx512bw")]
#[stable(feature = "stdarch_x86_avx512", since = "1.89")]
#[cfg_attr(test, assert_instr(vpackusdw))]
#[cfg_attr(test, assert_instr(vpackusdw, limit(5), not(vpminsd), not(vpmaxsd)))]
pub fn _mm512_packus_epi32(a: __m512i, b: __m512i) -> __m512i {
unsafe { transmute(vpackusdw(a.as_i32x16(), b.as_i32x16())) }
}
Expand Down Expand Up @@ -6807,7 +6807,7 @@ pub fn _mm_maskz_packus_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i {
#[inline]
#[target_feature(enable = "avx512bw")]
#[stable(feature = "stdarch_x86_avx512", since = "1.89")]
#[cfg_attr(test, assert_instr(vpackuswb))]
#[cfg_attr(test, assert_instr(vpackuswb, limit(5), not(vpminsw), not(vpmaxsw)))]
pub fn _mm512_packus_epi16(a: __m512i, b: __m512i) -> __m512i {
unsafe { transmute(vpackuswb(a.as_i16x32(), b.as_i16x32())) }
}
Expand Down
6 changes: 3 additions & 3 deletions crates/core_arch/src/x86/sse2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,7 @@ pub const fn _mm_move_epi64(a: __m128i) -> __m128i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi16)
#[inline]
#[target_feature(enable = "sse2")]
#[cfg_attr(test, assert_instr(packsswb))]
#[cfg_attr(test, assert_instr(packsswb, limit(5), not(pminsw), not(pmaxsw)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i {
unsafe { transmute(packsswb(a.as_i16x8(), b.as_i16x8())) }
Expand All @@ -1508,7 +1508,7 @@ pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32)
#[inline]
#[target_feature(enable = "sse2")]
#[cfg_attr(test, assert_instr(packssdw))]
#[cfg_attr(test, assert_instr(packssdw, limit(5), not(pminsd), not(pmaxsd)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i {
unsafe { transmute(packssdw(a.as_i32x4(), b.as_i32x4())) }
Expand All @@ -1520,7 +1520,7 @@ pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16)
#[inline]
#[target_feature(enable = "sse2")]
#[cfg_attr(test, assert_instr(packuswb))]
#[cfg_attr(test, assert_instr(packuswb, limit(5), not(pminsw), not(pmaxsw)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i {
unsafe { transmute(packuswb(a.as_i16x8(), b.as_i16x8())) }
Expand Down
2 changes: 1 addition & 1 deletion crates/core_arch/src/x86/sse41.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ pub const fn _mm_min_epu32(a: __m128i, b: __m128i) -> __m128i {
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32)
#[inline]
#[target_feature(enable = "sse4.1")]
#[cfg_attr(test, assert_instr(packusdw))]
#[cfg_attr(test, assert_instr(packusdw, limit(5), not(pminsd), not(pmaxsd)))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub fn _mm_packus_epi32(a: __m128i, b: __m128i) -> __m128i {
unsafe { transmute(packusdw(a.as_i32x4(), b.as_i32x4())) }
Expand Down
Loading