Uh oh!
There was an error while loading. Please reload this page.
Mir-Opt for copying enums with large discrepancies - #85158
Conversation
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
tmiasko
left a comment
There was a problem hiding this comment.
Hmm, so the idea is to transform: _a = _b; into:
_index = discriminant(_b);
_bytes = [size of each variant in bytes][_index]
CopyNonOverlapping(src: &_b as *const u8, dst: &_a as *mut u8, count: _bytes);
The transformation is localized to a single assignment, requires layout information, some aspects of it feel non-trivial to express directly in MIR (e.g., preserving the alignment). Maybe codegen would be a better fit?
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
tmiasko
commented
May 12, 2021
This general pattern for copying the data appears to be opaque to memcpy optimizations, i.e., every single transformed copy remains. Any ideas how this could be improved? |
scottmcm
commented
May 12, 2021
That would mean it would have the monomorphized versions of the enum too, right? Could be handy for anything using a generic |
JulianKnodt
commented
May 12, 2021
Mmmm I've not written anything for codegen at all, but if that makes more sense I can close this and move it to that, altho seeing a guide before it would be helpful. |
tmiasko
commented
May 12, 2021
As you prefer. The current implementation is not that far from the point where we could run some tests on it. The one missing component is a mapping from a discriminant to a variant index (or limiting the transformation to the cases where there is direct correspondence between the two). |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
JulianKnodt
commented
May 12, 2021
ah I thought reading from the array of sizes was handled around line 132, but I guess mapping discriminants to variant idxes is not guaranteed to be 1-1, is there anyway to check that? |
bjorn3
commented
May 13, 2021
I believe enumFoo{Bar = 2,Baz = 0,}has variant index 0 for |
Uh oh!
There was an error while loading. Please reload this page.
tmiasko
commented
May 13, 2021
The |
camelid
commented
May 28, 2021
Does this fix #54360? |
JulianKnodt
commented
May 28, 2021
I believe so? I don't remember the original issue. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
The max - min criterion is based on the most optimistic scenario.
Consider two enums with the same maximum absolute deviation in variant sizes. The first enum has one large outlier and remaining variants are small, the second enum conversely has one small outlier and remaining variants are large. Both enums would be be equally good candidates under current criterion, but the first one would seem like a much better candidate.
What about assuming that variants are uniformly distributed and calculating expected reduction in the number of bytes copied?
There was a problem hiding this comment.
oops I never directly addressed this, I'm not sure if uniform distribution makes a ton of sense, as I'd expect if this is hit that one variant is probably significantly larger than the others. Probably something to experiment with.
tmiasko
commented
May 28, 2021
In terms of placement in MIR pipeline, I would put it towards the end, somewhere after SimplifyLocals, maybe just last? I wouldn't expect it to create any new optimization opportunities. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
oli-obk
commented
Feb 4, 2023
@bors ping |
oli-obk
commented
Feb 4, 2023
@bors r=wesleywiser |
bors
commented
Feb 4, 2023
📌 Commit d87d939f99fcb16b3960cd7238405b4b5e0bc391 has been approved by It is now in the queue for this repository. |
bors
commented
Feb 4, 2023
⌛ Testing commit d87d939f99fcb16b3960cd7238405b4b5e0bc391 with merge 97a7629360c6bd2c321a5bd1ecaa2433a5d49bd7... |
bors
commented
Feb 4, 2023
💔 Test failed - checks-actions |
This comment has been minimized.
This comment has been minimized.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I've just turned wasm off on the test for now... either way it should be fine since both are correct. I forget if there were other issues that cropped up outside of wasm oops, android was also failing for some reason so I should look into that |
This comment has been minimized.
This comment has been minimized.
Still need to make it so that it maps discriminants to variant indexes. Maybe instead I can map the variant indexes to discriminants?
Changing a bunch of struct constructors to `from`, no extra destructuring, getting the type of the discriminant.
Since we're changing a bunch of stuff, necessary to remove some codegen tests which look for specific things. Also attempting to restart a test which timed out, maybe due to fastly failing?
Instead of storing an extra array for discriminant values, create an allocation there and store those in an allocation immediately.
There is a distinction between running this on wasm and i686, even though they should be identical. This technically is not _incorrect_, it's just an unexpected difference, which is worth investigating, but not for correctness.
Uh oh!
There was an error while loading. Please reload this page.
JulianKnodt
commented
Feb 8, 2023
Should be ok to retry submitting again at this point |
cjgillot
commented
Feb 10, 2023
@bors r+ |
bors
commented
Feb 10, 2023
bors
commented
Feb 10, 2023
bors
commented
Feb 11, 2023
☀️ Test successful - checks-actions |
rust-timer
commented
Feb 11, 2023
Finished benchmarking commit (5a8dfd9): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. |
| impl<'tcx> MirPass<'tcx> for EnumSizeOpt { | ||
| fn is_enabled(&self, sess: &Session) -> bool { | ||
| sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3 |
There was a problem hiding this comment.
I think this commit changed the logic accidentally? This should have been unsound_mir_opts && level >= 3. Otherwise this still gets enabled despite being unsound!
I'll make a PR.
I have been meaning to make this for quite a while, based off of this hackmd.
I'm not sure where to put this opt now that I've made it, so I'd appreciate suggestions on that!
It's also one long chain of statements, not sure if there's a more friendly format to make it.
r? @tmiasko
I would
roli but he's on leave so he suggested Irtmiasko or wesleywiser.