Shrink from_raw_parts's MIR so that Vec::deref MIR-inlines again#123190
Shrink from_raw_parts's MIR so that Vec::deref MIR-inlines again#123190scottmcm wants to merge 2 commits intorust-lang:masterfrom
from_raw_parts's MIR so that Vec::deref MIR-inlines again#123190Conversation
This comment has been minimized.
This comment has been minimized.
fcea56f to
3e4a577
Compare
This comment has been minimized.
This comment has been minimized.
saethlin
left a comment
There was a problem hiding this comment.
The new MIR looks a lot nicer; the previous MIR I think had a lot of union juggling that we don't have a MIR opt to clean up. The codegen test here demonstrates the improvement to inlining but can you post the before and after Vec::deref so everyone can see?
|
Hm, I'm not happy with making our libcore a tangled mess just to get the MIR a bit nicer. That's a maintenance nightmare... |
|
🤷 I'm leaving that decision up to libs. It's possible to get the inlining here by other means, but I'm not sure what MIR optimizations are required to clean up |
a3bb26f to
e27ce30
Compare
|
I've pushed a rearrangement of things to attempt to address the "tangled mess" concerns. There's now a (non-exported) The resulting diffs outside the new module, such as pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
- from_raw_parts(data.cast(), len)
+ internal_repr::from_raw_parts(data, len)
}seem entirely fine to me. Like the previous iteration, there's no more need for Personally I rather like it, since it lets stuff elsewhere in the library keep using the pointers they already have, rather than needing to cast them or wrap/unwrap them. (For all that an extra |
This comment has been minimized.
This comment has been minimized.
|
#122975 means that what you see below is very different from the previous nightly, but that change on its own isn't enough to get Before this PR, with adding bb0: {
StorageLive(_4);
StorageLive(_2);
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_3);
_3 = ((((*_1).0: alloc::raw_vec::RawVec<u8>).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
_4 = (_3.0: *const u8);
StorageDead(_3);
StorageDead(_2);
StorageLive(_5);
_5 = ((*_1).1: usize);
StorageLive(_6);
_6 = _4 as *const () (PtrToPtr);
StorageLive(_8);
StorageLive(_7);
_7 = std::ptr::metadata::PtrComponents::<[u8]> { data_pointer: _6, metadata: _5 };
_8 = std::ptr::metadata::PtrRepr::<[u8]> { const_ptr: move _7 };
StorageDead(_7);
_9 = (_8.0: *const [u8]);
StorageDead(_8);
StorageDead(_6);
StorageDead(_5);
StorageDead(_4);
_0 = &(*_9);
return;
}After this PR: bb0: {
StorageLive(_4);
StorageLive(_2);
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_3);
_3 = ((((*_1).0: alloc::raw_vec::RawVec<u8>).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
_4 = (_3.0: *const u8);
StorageDead(_3);
StorageDead(_2);
StorageLive(_5);
_5 = ((*_1).1: usize);
StorageLive(_6);
_6 = std::ptr::internal_repr::PtrComponents::<*const u8, usize> { data_pointer: _4, metadata: _5 };
_7 = move _6 as *const [u8] (Transmute);
StorageDead(_6);
StorageDead(_5);
StorageDead(_4);
_0 = &(*_7);
return;
}After the post-inlining simplifications the difference is just that one less cast and a |
e27ce30 to
013c383
Compare
|
Should we have a pass that turns transmute-via-union into a transmute statement? |
|
I'd love to have a real InstCombine pass that can easily look at multiple statements at once. Any progress on one since #105808? |
|
Not from me. Anyone can resurrect the general strategy in that PR, so long as they have a fix for the storage liveness issue @cjgillot pointed out. It's somewhere in the PR comments, I can't load the page right now to find it. |
|
Taking a step back, we may need to rethink how we create and use wide pointers in MIR. I wonder if we should go towards:
The fact that Vec::deref would look something like: Bonus: this may allow to simplify slice construction, as current GVN is unable to understand the union dance. |
|
It doesn't make much sense to have slice construction implemented in the library like it is now. I'm pretty sure |
|
☔ The latest upstream changes (presumably #123484) made this pull request unmergeable. Please resolve the merge conflicts. |
|
Closing in favour of #123840 |
…gillot Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes rust-lang#123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
…cjgillot Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes rust-lang#123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
…cjgillot Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes rust-lang#123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
Rollup merge of rust-lang#123840 - scottmcm:aggregate-kind-rawptr, r=cjgillot Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes rust-lang#123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes #123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang/rust#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
Add an intrinsic for `ptr::from_raw_parts(_mut)` Fixes #123174 cc `@CAD97` `@saethlin` r? `@cjgillot` As suggested in rust-lang/rust#123190 (comment), this adds a new `AggregateKind::RawPtr` for creating a pointer from its data pointer and its metadata. That means that `slice::from_raw_parts` and friends no longer need to hard-code pointer layout into `libcore`, and because it no longer does union hacks the MIR is shorter and more amenable to optimizations.
Fixes #123174
cc @CAD97
Two commits; the first adds the codegen test so that you can see the diff clearly in the second commit.