[mir-opt] Allow SRoA when an object is transmuted to a field type#158291
[mir-opt] Allow SRoA when an object is transmuted to a field type#158291scottmcm wants to merge 1 commit into
Conversation
|
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
…d, r=aapoalas
Implement `ptr::{read,write}_unaligned` via `repr(packed)`
We already support doing unaligned reads & writes via `repr(packed)` fields, so this just uses that support from the backend rather than needing to thinks about `memcpy` and `intrinsics::forget` and such.
Turns out in codegen this ends up essentially identical because the packed type read gets `BackendRepr::Memory` and thus the read/write of the packed type *is* an `align 1` memcpy, just like the library code before this PR. But doing this gives much simpler MIR and rust-lang#158291 will make it better than the previous version by not needing to emit the `memcpy` at all for things like `read_unaligned::<u32>`.
First commit are some tests that pass on master; Second commit changes the implementation and shows the corresponding test changes.
r? libs
…d, r=aapoalas
Implement `ptr::{read,write}_unaligned` via `repr(packed)`
We already support doing unaligned reads & writes via `repr(packed)` fields, so this just uses that support from the backend rather than needing to thinks about `memcpy` and `intrinsics::forget` and such.
Turns out in codegen this ends up essentially identical because the packed type read gets `BackendRepr::Memory` and thus the read/write of the packed type *is* an `align 1` memcpy, just like the library code before this PR. But doing this gives much simpler MIR and rust-lang#158291 will make it better than the previous version by not needing to emit the `memcpy` at all for things like `read_unaligned::<u32>`.
First commit are some tests that pass on master; Second commit changes the implementation and shows the corresponding test changes.
r? libs
7ed426a to
fd33c1f
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
fd33c1f to
a576ef9
Compare
| StorageLive(_4); | ||
| _4 = copy (*_3); | ||
| _5 = copy _4 as T (Transmute); | ||
| StorageDead(_4); | ||
| _4 = copy ((*_3).0: T); |
There was a problem hiding this comment.
The library change to use packed landed in #158427, so now this shows the critical change from this optimization...
| // CHECK-NOT: !noundef | ||
| // CHECK-NOT: !range | ||
| // CHECK-SAME: !range [[R16:![0-9]+]] | ||
| // CHECK-SAME: !noundef |
There was a problem hiding this comment.
...which then means these loads get metadata on them without codegen changes.
|
The more I poked at this the less I'm confident that SRoA is the correct answer here, especially since I tried going a bit further and ended up just getting things like this bb0: {
StorageLive(_3);
_3 = PtrMetadata(copy _1);
StorageLive(_5);
StorageLive(_4);
_4 = &raw const (*_1);
- _5 = copy _4 as std::ptr::NonNull<[T]> (Transmute);
+ _5 = copy _4 as (*const [T]) is !null (Transmute);
StorageDead(_4);
StorageLive(_7);
StorageLive(_6);
_6 = copy _5 as *mut [T] (Transmute);
_7 = copy _6 as *mut T (PtrToPtr);
StorageDead(_6);
- _8 = copy _7 as std::ptr::NonNull<T> (Transmute);
+ _8 = copy _7 as (*const T) is !null (Transmute);
StorageDead(_7);
StorageDead(_5);
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
}which is kinda the opposite of the direction in #153085 which I think would be nicer to see when reading the MIR. |
Inspired by #158202 (comment), this allows SRoA to expand a local consumed by a
CastKind::Transmuteif that transmute is to the type of a field, since if it's to the type of a field we can just have it take the local for that field like we would if it was a field projection.Future PRs could do more complex stuff, like using layout to always allow SRoA of
xinTransmute(x)when x is https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/layout/type.TyAndLayout.html#method.non_1zst_field, but this is enough for the specific case I needed.r? mir-opt