-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Optimize the way that loans are killed in borrowck dataflow #51106
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
Conversation
As of writing this and creating this PR - this pull request builds and I've implemented something that roughly matches how I read the issue and instructions - I don't believe it passes all the tests though and I've not had a chance to look into that yet. I also don't know if it has better performance, not sure what the standard mechanism for checking that is. Update: Pushed a commit that seems to be fixing some of the errors I was seeing - though I've not had time to run all the tests. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Pushed up a fix that should stop the DFS getting stuck in cycles. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
// If we're not on the last statement, then go to the next | ||
// statement in this block. | ||
} else { | ||
precompute_borrows_out_of_scope(mir, regioncx, borrows_out_of_scope_at_location, |
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.
Is llvm able to tail call optimize this?
borrows_out_of_scope_at_location | ||
.entry(location.clone()) | ||
.and_modify(|m| m.push(borrow_index)) | ||
.or_insert(vec![ borrow_index ]); |
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.
Wait, you should return here. That is, once the borrow goes out of scope, we kill it, but we can stop the DFS at that point.
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.
Also, wouldn't this normally be
borrows_out_of_scope_at_location
.entry(location)
.or_insert_with(vec![])
.push(borrow_index);
That seems strictly better... among other things, the formulation as you wrote it here will allocate a vector even when it is not needed.
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.
(Not returning here may be the source of the problem... but I don't see immediately why, it just seems like it would result in vectors that are (much) bigger than necessary.)
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.
Pushed a commit that addresses this.
// If we are past the last statement, then check the terminator | ||
// to determine which location to proceed to. | ||
if location.statement_index == bb_data.statements.len() { | ||
if let Some(ref terminator) = bb_data.terminator { |
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.
you can invoke the successors
method on the terminator instead, would be easier =)
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 wish I'd noticed that earlier - fixed.
borrow_region: RegionVid, | ||
location: Location, | ||
visited_locations: &mut Vec<Location> | ||
) { |
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.
Nit: I would definitely write this method with a loop
. My usual formulation is something like this:
let mut stack = vec![location];
let mut visited = FxHashSet();
visited.insert(location);
while let Some(p) = stack.pop() {
process(p);
for each n in successors(p) {
if visited.insert(n) {
stack.push(n);
}
}
}
In this case, process(p)
would be something like this:
if !regioncx.region_contains_point(borrow_region, location) {
borrows_out_of_scope_at_location
.entry(p)
.or_insert_with(vec![])
.push(borrow_index);
continue; // do not visit successors of this point
}
and of course successors(p)
is either a call to Terminator::successors
or else successor_within_block
— not sure if we have a more concise way to get that result right now...
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.
That is much cleaner, not sure what I was thinking when I did it recursively. Fixed this.
…orrow is out of scope at location.
Pushed up a commit that refactors and addresses previous points. Testing locally shows that this fails even more tests, mostly with the same "could not find any constraint to blame for" error repeated in different tests. |
@bors try |
⌛ Trying commit 3a9134d with merge 01aca8254fefbace3ec9fa9de8214cae2f7a07cd... |
@Mark-Simulacrum it'd be good to get a perf run on this branch |
we expect it to be faster, but I suppose it's possible for it to be slower :) |
I've queued the build.. in theory it'll finish before perf gets to it and work smoothly, but if not I'll queue again in a couple hours. |
☀️ Test successful - status-travis |
@Mark-Simulacrum ok, try run succeeded now in any case. Approximately how long does a perf run take? |
@bors r+ OK, I am not able to get perf to work, as usual. =( This URL doesn't seem to have any data However, I'm going to r+, because local measurements suggest this is indeed a win. |
📌 Commit 3a9134d has been approved by |
@bors p=1 Giving high priority because getting NLL performant is a 2018 Edition blocker. |
Optimize the way that loans are killed in borrowck dataflow Fixes #50934. r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
Fixes #50934.
r? @nikomatsakis