From/Into arrays for core::arch SIMD types?

Currently it's cumbersome to get data in or out of non-portable SIMD types like __m128 or float32x4_t.

  • The load/store intrinsics require raw pointers like *const f32, which needs a combo of .as_ptr().cast().
  • Having a *mut f32 pointer to load into requires creating an array first, which needs extra lines of code, and requires initializing it. Trying to explicitly avoid init (as opposed to hoping the raw pointer won't prevent the compiler from optimizing out the init), requires [MaybeUninit<f32>; 4], which adds even more ceremony.
  • The code is forced to pick a specific load/store intrinsic, but that doesn't actually matter! Behind the scenes they are implemented using core::ptr::read_unaligned or mem::transmute, and the optimizer does whatever it wants with them.
  • In practice, everyone uses mem::transmute instead. However, this is a powerful function, and it raises doubt whether this is the correct thing to do, or maybe something hacky that may be UB.

Is there anything stopping core::arch SIMD types from implementing From<[f32; 4]> etc? If this needs to be unsafe, how about an inherent unsafe fn into_array/from_array?

4 Likes

Hmm, https://doc.rust-lang.org/std/simd/struct.Simd.html#impl-From<Simd<u16,+8>>-for-__m128i exists, so on nightly you can do this as Simd::from_array(...).into().

TBH this feels expected for arch simd. I agree it's not nice, but nothing about using arch simd intrinsics is nice :stuck_out_tongue:

1 Like