Conversation
SIMD-style optimizations are the most common use for `[T]::align_to(_mut)`, but that's `unsafe`. So these are *safe* wrappers around it, now that we have the `Simd` type available, to make it easier to use.
```rust
impl [T] {
pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]);
pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]);
}
```
|
r? @yaahc (rust-highfive has picked a reviewer for you, use r? to override) |
|
cc @workingjubilee in case this is a terrible idea for some reason |
workingjubilee
left a comment
There was a problem hiding this comment.
This looks fine, modulo the question it raises and the nits.
library/core/src/slice/mod.rs
Outdated
| } | ||
| } | ||
|
|
||
| /// Split a slice into a prefix, a middle of aligned simd types, and a suffix. |
There was a problem hiding this comment.
| /// Split a slice into a prefix, a middle of aligned simd types, and a suffix. | |
| /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. |
library/core/src/slice/mod.rs
Outdated
| /// This is a safe wrapper around [`slice::align_to`], so has the same weak | ||
| /// preconditions as that method. Notably, you must not assume any particular | ||
| /// split between the three parts: it's legal for the middle slice to be | ||
| /// empty even if the input slice is longer than `3 * LANES`. |
There was a problem hiding this comment.
Since this wrapper is safe, this should clarify that this is an invalid assumption for unsafe code, as the function can no longer be relied upon to maintain invariants in the same way. Safe code trying to "rely" on it would be "merely" logically incorrect.
There was a problem hiding this comment.
Oh, I wrote "preconditions" here when I meant "postconditions" 🤦
library/core/src/slice/mod.rs
Outdated
| unsafe { self.align_to() } | ||
| } | ||
|
|
||
| /// Split a slice into a prefix, a middle of aligned simd types, and a suffix. |
There was a problem hiding this comment.
| /// Split a slice into a prefix, a middle of aligned simd types, and a suffix. | |
| /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. |
| // SAFETY: The simd types have the same layout as arrays, just with | ||
| // potentially-higher alignment, so the de-facto transmutes are sound. | ||
| unsafe { self.align_to() } |
There was a problem hiding this comment.
Sound, yes, but it would likely exhibit unexpected behavior if LANES is an odd number (like 3), as that would potentially result in bytes no longer being read (because the stride of the type will be as if LANES is 4). This is not supported yet, but we have not yet ruled this possibility out. This function therefore introduces an unanswered question. Should we:
- allow people to transmute data into padding
- add additional bounds on this if we relax those on
LANES - rule out types like
Simd<f32, 3>entirely?
There was a problem hiding this comment.
Well I guess my assert_eq on the sizes (line 3487) is more useful than I'd thought, as if 3-simd is padded out to 4-simd it'd make the function just panic instead of skipping things.
The other possibility would be to have it just return everything in the prefix for that case, since align_to is allowed to do that anyway (for MIRI), and it'd just be slower than desired if someone uses the non-power-of-two sizes.
There was a problem hiding this comment.
I didn't consider that, but it is indeed also an option!
This is definitely a bridge we can cross when we actually come to it, I just wanted to note the bridge is indeed up ahead.
|
lgtm once all the comments are resolved |
|
@workingjubilee I've pushed updates; please take a look and see if they satisfactorily address your comments. And since it's LGTM from yaahc, |
|
✌️ @workingjubilee can now approve this pull request |
|
Yeah, this looks fine! |
|
📌 Commit e4c44c5 has been approved by |
…bilee
Add `[T]::as_simd(_mut)`
SIMD-style optimizations are the most common use for `[T]::align_to(_mut)`, but that's `unsafe`. So these are *safe* wrappers around it, now that we have the `Simd` type available, to make it easier to use.
```rust
impl [T] {
pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T]);
pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T]);
}
```
They're `cfg`'d out for miri because the `simd` module as a whole is unavailable there.
…askrgr Rollup of 7 pull requests Successful merges: - rust-lang#90521 (Stabilize `destructuring_assignment`) - rust-lang#91479 (Add `[T]::as_simd(_mut)`) - rust-lang#91584 (Improve code for rustdoc-gui tester) - rust-lang#91886 (core: minor `Option` doc correction) - rust-lang#91888 (Handle unordered const/ty generics for object lifetime defaults) - rust-lang#91905 (Fix source code page sidebar on mobile) - rust-lang#91906 (Removed `in_band_lifetimes` from `library\proc_macro`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
The SIMD module is only commented out for doctests, but otherwise available... but I guess that is enough to require these extra cfg here. Which is a shame because I only wanted to disable the tests in Miri, not actually hide any APIs. If there are better ways to disable doctests in a part of a crate, I'd be interested to learn about them. :) |
SIMD-style optimizations are the most common use for
[T]::align_to(_mut), but that'sunsafe. So these are safe wrappers around it, now that we have theSimdtype available, to make it easier to use.They're
cfg'd out for miri because thesimdmodule as a whole is unavailable there.