Getting explicit SIMD on stable Rust

AFAICT, there is basically only one option: if monomorphization leads to a function either passing a SIMD type as an argument or receiving one as a return value, it must be compiled with the appropriate target feature. Anything else seems like it would lead to either monomorphization-time errors or surprising behavior.

Here are two suggestions to mitigate the unfortunate implicitness:

  • pre-monomorphization, it is a compile error to pass a SIMD type or get one as a return value, unless you are in a function that is compiled with the appropriate target feature. This limits the implicit target_feature propagation to generic functions, and doesn't introduce any post-monomorphization errors.

  • post-monomorphization, it is a warning to call a monomorphized function that got an implicit target feature, unless you are calling from a function with that target feature (implicit or not). There would be an attribute to silence this warning, since it's legitimate to do this after a runtime CPU feature check.

The implication of the first rule for @burntsushi's examples: in

#[inline(always)]
#[target_feature = "+avx2"]
fn testfoo(x: i64, y: i64, shift: i32) -> i64 {
    let a = i64x4(x, x, y, y);
    _mm256_slli_epi64(a, shift).0
}

it would be a compile-time error to leave off target_feature, regardless of whether inline is specified. In

#[target_feature = "+avx2"]
fn testfoo(x: i64, y: i64, shift: i32) -> i64x4 {
    let a = i64x4(x, x, y, y);
    _mm256_slli_epi64(a, shift)
}

it would be a compile-time error to call testfoo from a function without an appropriate target_feature (avx or avx2).

1 Like