Right now (#347), #[simd] requires the first non-receiver argument to a SIMD token. However, it's not uncommon for SIMD functions to not have an explicit SIMD token parameter, because any SIMD type (e.g. f32xN, etc) already carries a SIMD token with them. For example, this is what the sRGB example does:
|
#[inline(always)] |
|
fn copy_alpha<S: Simd>(a: f32x4<S>, b: f32x4<S>) -> f32x4<S> { |
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
|
if let Some(sse4_2) = a.simd.level().as_sse4_2() { |
|
return copy_alpha_sse4_2(sse4_2, a.into(), b.into()).simd_into(a.simd); |
|
} |
|
|
|
#[cfg(target_arch = "aarch64")] |
|
if let Some(neon) = a.simd.level().as_neon() { |
|
return copy_alpha_neon(neon, a.into(), b.into()).simd_into(a.simd); |
|
} |
|
|
|
let mut result = a; |
|
result[3] = b[3]; |
|
result |
|
} |
Such functions should be supported to make the #[simd] macro easier to use.
Suggested solution
Instead of requiring that the first parameter is a SIMD token, require that the first parameter carries a SIMD token.
This could be done by adding a new trait like so:
pub trait ExtractToken { // bikeshed names
type S: Simd;
fn simd(&self) -> Self::S;
}
// all SIMD token types return self
impl ExtractToken for Avx2 {
type S = Self;
fn simd(&self) -> Self::S {
*self
}
}
// all data type return their SIMD token
impl<S: Simd> ExtractToken for f32x8<S> {
type S = S;
fn simd(&self) -> Self::S {
self.simd
}
}
and change the code gen of the #[simd] macro to use this trait to get a SIMD token from the first parameter.
By adding #[diagnostic::on_unimplemented] on the trait, we can also get nice compiler errors when users use #[simd] incorrectly. E.g.
#[simd]
fn foo<S: Simd>(a: i32);
error[E0277]: `i32` does not carry a SIMD token
--> src\encode\bc4.rs:961:24
|
961 | ExtractToken::simd(&a)
| ------------------ ^^ the trait `fearless_simd::ExtractToken` is not implemented for `i32`
| |
| required by a bound introduced by this call
|
= note: If you are using the #[simd] macro, the first parameter must carry a SIMD token. See the docs of #[simd] for more information.
help: the following other types implement trait `fearless_simd::ExtractToken`
--> ...
Note: I think the ExtractToken trait should be part of the public API of the main crate. I want to implement it on the newtype wrappers around fearless_simd types I use.
Right now (#347),
#[simd]requires the first non-receiver argument to a SIMD token. However, it's not uncommon for SIMD functions to not have an explicit SIMD token parameter, because any SIMD type (e.g.f32xN, etc) already carries a SIMD token with them. For example, this is what thesRGBexample does:fearless_simd/fearless_simd/examples/srgb.rs
Lines 52 to 67 in bd9f7c7
Such functions should be supported to make the
#[simd]macro easier to use.Suggested solution
Instead of requiring that the first parameter is a SIMD token, require that the first parameter carries a SIMD token.
This could be done by adding a new trait like so:
and change the code gen of the
#[simd]macro to use this trait to get a SIMD token from the first parameter.By adding
#[diagnostic::on_unimplemented]on the trait, we can also get nice compiler errors when users use#[simd]incorrectly. E.g.Note: I think the
ExtractTokentrait should be part of the public API of the main crate. I want to implement it on the newtype wrappers aroundfearless_simdtypes I use.