Layout of packed SIMD vectors
Disclaimer: This chapter represents the consensus from issue #38. The statements in here are not (yet) "guaranteed" not to change until an RFC ratifies them.
Rust currently exposes packed^{1} SIMD vector types like __m128
to users, but it
does not expose a way for users to construct their own vector types.
The set of currentlyexposed packed SIMD vector types is implementationdefined and it is currently different for each architecture.
packed denotes that these SIMD vectors have a compiletime fixed size, distinguishing these from SIMD vector types whose size is only known at runtime. Rust currently only supports packed SIMD vector types. This is elaborated further in RFC2366.
Packed SIMD vector types
Packed SIMD vector types are repr(simd)
homogeneous tuplestructs containing
N
elements of type T
where N
is a poweroftwo and the size and alignment
requirements of T
are equal:
#[repr(simd)]
struct Vector<T, N>(T_0, ..., T_(N  1));
The set of supported values of T
and N
is implementationdefined.
The size of Vector
is N * size_of::<T>()
and its alignment is an
implementationdefined function of T
and N
greater than or equal to
align_of::<T>()
. That is:
assert_eq!(size_of::<Vector<T, N>>(), size_of::<T>() * N);
assert!(align_of::<Vector<T, N>>() >= align_of::<T>());
That is, two distinct repr(simd)
vector types that have the same T
and the
same N
have the same size and alignment.
Vector elements are laid out in source field order, enabling random access to vector elements by reinterpreting the vector as an array:
union U {
vec: Vector<T, N>,
arr: [T; N]
}
assert_eq!(size_of::<Vector<T, N>>(), size_of::<[T; N]>());
assert!(align_of::<Vector<T, N>>() >= align_of::<[T; N]>());
unsafe {
let u = U { vec: Vector<T, N>(t_0, ..., t_(N  1)) };
assert_eq!(u.vec.0, u.arr[0]);
// ...
assert_eq!(u.vec.(N  1), u.arr[N  1]);
}
Unresolved questions

Blocked: Should the layout of packed SIMD vectors be the same as that of homogeneous tuples ? Such that:
union U { vec: Vector<T, N>, tup: (T_0, ..., T_(N1)), } assert_eq!(size_of::<Vector<T, N>>(), size_of::<(T_0, ..., T_(N1))>()); assert!(align_of::<Vector<T, N>>() >= align_of::<(T_0, ..., T_(N1))>()); unsafe { let u = U { vec: Vector(t_0, ..., t_(N  1)) }; assert_eq!(u.vec.0, u.tup.0); // ... assert_eq!(u.vec.(N  1), u.tup.(N  1)); }
This is blocked on the resolution of issue #36 about the layout of homogeneous structs and tuples.

MaybeUninit<T>
does not have the samerepr
asT
, soMaybeUninit<Vector<T, N>>
are notrepr(simd)
, which has performance consequences and means thatMaybeUninit<Vector<T, N>>
is not CFFI safe.