-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MIR opt: Expand aggregates into multiple locals #85796
Conversation
r? @varkor (rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Related: #48300 was a previous attempt at this |
} | ||
|
||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { | ||
if place.projection.is_empty() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should play safe and reject all locals that have their address taken. Whether only for a part of as a whole. At least until we have better support for handling references in mir opts.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #85804) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment has been minimized.
This comment has been minimized.
I don't have time to review this at the moment. Going to reassign to r? @bjorn3 who's more familiar with this code. |
r? @RalfJung This optimization depends on the exact semantics of MIR and we have had miscompilations due to incorrect MIR optimizations before. As such I don't feel comfortable signing off on a MIR optimization. |
I can help with advice on MIR semantics, but I won't have time to review a PR of this size any time soon I am afraid. |
No problem. I will try to taken review on myself then, but I would like it to either land behind either r? @bjorn3 |
☔ The latest upstream changes (presumably #85891) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment has been minimized.
This comment has been minimized.
Triage: Seems CI is still red. |
Queued 2a09f2c20f1895c61a8f6f6a3a484627b2327ce4 with parent d9aa287, future comparison URL. |
Finished benchmarking try commit (2a09f2c20f1895c61a8f6f6a3a484627b2327ce4): comparison url. Summary: This change led to significant mixed results 🤷 in compiler performance.
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf. Next Steps: If you can justify the regressions found in this perf run, please indicate this with @bors rollup=never |
return; | ||
} | ||
|
||
match self.map.fields.entry(place.clone()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PlaceRef implements copy, so clone should be unnecessary.
&flatten_locals::FlattenLocals, | ||
&remove_storage_markers::RemoveStorageMarkers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemoveStorageMarkers
removes the storage markers at opt-level=0. Reordering those two passes would avoid needles expansion of storage markers during flattening.
return None; | ||
} | ||
let mut expanded = Vec::new(); | ||
for (k, &v) in &replacements.fields { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be quadratic in the MIR size in the worst case. Could we avoid that?
Some(expanded.into_iter()) | ||
}); | ||
} | ||
super::simplify::simplify_locals(body, tcx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does running simplify locals immediately after flattening have additional benefits compared to leaving this clean-up for later?
Benchmarks that slightly regressed include check and doc builds. I would suspect that this is mostly a side effect of different partitioning while building rustc. It could be interesting to run perf comparison while keeping partitioning fixed, e.g., by always returning 1 from |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #80522) made this pull request unmergeable. Please resolve the merge conflicts. |
StatementKind::StorageDead(l) => (false, *l), | ||
_ => return None, | ||
}; | ||
replaced_locals.get(origin_local).map(move |final_locals| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removes storage markers for locals without any replacements (replaced_locals
is an IndexVec
now, so get
doesn't have desired effect).
Other than the issue with storage markers, the implementation looks good to me. The perf results are mostly a regression, though? |
Perform simple scalar replacement of aggregates (SROA) MIR opt This is a re-open of rust-lang#85796 I copied the debuginfo implementation (first commit) from `@eddyb's` own SROA PR. This pass replaces plain field accesses by simple locals when possible. To be eligible, the replaced locals: - must not be enums or unions; - must not be used whole; - must not have their address taken. The storage and deinit statements are duplicated on each created local. cc `@tmiasko` who reviewed the former version of this PR.
Perform simple scalar replacement of aggregates (SROA) MIR opt This is a re-open of rust-lang/rust#85796 I copied the debuginfo implementation (first commit) from `@eddyb's` own SROA PR. This pass replaces plain field accesses by simple locals when possible. To be eligible, the replaced locals: - must not be enums or unions; - must not be used whole; - must not have their address taken. The storage and deinit statements are duplicated on each created local. cc `@tmiasko` who reviewed the former version of this PR.
Perform simple scalar replacement of aggregates (SROA) MIR opt This is a re-open of rust-lang/rust#85796 I copied the debuginfo implementation (first commit) from `@eddyb's` own SROA PR. This pass replaces plain field accesses by simple locals when possible. To be eligible, the replaced locals: - must not be enums or unions; - must not be used whole; - must not have their address taken. The storage and deinit statements are duplicated on each created local. cc `@tmiasko` who reviewed the former version of this PR.
The MIR deaggregator expands aggregate assignments into field accesses, downcasts and discriminant assignments. However, this creates needlessly complicated place projections that may limit later optimization passes.
This PR attempts to replace those accesses by new locals that can be optimized more easily, for instance by DestProp.