SIMD Intrinsics + Cell?

I'm writing some code without intrinsics but I am trying to plan the memory layout so it will be easier to switch to intrinsics later (using AOS style instead of SOA).

One issue is that my data structure is expected to be used in context where there are multiple references to mutable data, so I need to use Cell. This means instead of arrays of f32 they are of Cell<f32>. I know technically all of the built-in intrinsics are considered unsafe, but I'm wondering whether or not it is UB to apply them to arrays of Cell<T>, provided I have taken care of making sure there is sufficient alignment to use the intrinsic? Is Cell<T> guaranteed to have the same memory layout as T? Are there other considerations for whether it is UB?

Yes. Cell is marked as repr(transparent), which guarantees that its representation in memory is the same of the underlying type. In this case, that's T. Curiously, the docs for the cell types make no mention of this. They probably should, because I think that changing this would be a bad breaking change.

Other than alignment, I don't think there are any other UB considerations here specific to Cell.

2 Likes

The matching layout is also implied by from_mut(&mut T) -> &Cell<T>, assuming there's no other indirection involved.

3 Likes

Is there anything special about calling Cell::get() that is helping the compiler understand aliasing is allowed? Since doing an intrinsic load of the memory backing the cell won't go through this. But still has the sort of semantics Cell wants where you are copying data out rather than getting a mutable reference.

It's not about Cell, it's about UnsafeCell: it's a lang item.

I think that relying on #[repr(transparent)] not specified as the docs is bad - if the docs don't mention it, it's probably an implementation detail.

I agree? That's why I said, "Curiously, the docs for the cell types make no mention of this. They probably should, because I think that changing this would be a bad breaking change."

It could also just be a rustdoc thing. The repr of a public API type should probably be noted somewhere in the doc rendering.

I understood that you said, "this is public, and so the docs should mention this" but I think "this is private, because the docs don't mention this". Sorry if I misunderstood you.

It does, if you click [+] Expand attributes.

The attribute is there, but it's not publicly visible what this is transparently wrapping. Its field is actually an UnsafeCell<T>, and then that transparently (and privately) wraps T. You need to know all of that to take advantage of the attribute.

1 Like
Cell::<[T]>::as_slice_of_cells(&self) -> &[Cell<T>]

proves, that either the std method is unsound or Cell must guarantee a transparent layout. This is part of the public API and thus the guarantee cannot be revoked except in the case of an unsoundness bug.