Skip to content

#[simd] should work on functions without an explicit SIMD token parameter #379

Description

@RunDevelopment

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions