-
Notifications
You must be signed in to change notification settings - Fork 301
relooper: Avoid recomputing strict_reachable_from in simple case #1827
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -225,7 +225,7 @@ impl RelooperState { | |
| return; | ||
| } | ||
|
|
||
| let local_successors = blocks | ||
| let local_successors: AdjacencyList = blocks | ||
| .iter() | ||
| .map(|(lbl, bb)| (lbl.clone(), bb.successors())) | ||
| .collect(); | ||
|
|
@@ -241,13 +241,21 @@ impl RelooperState { | |
| // blocks. Global reachability won't work here because when we're inside a loop | ||
| // body we don't want to consider back edges, which we strip before processing | ||
| // the loop body. | ||
| let strict_reachable_from = flip_edges(transitive_closure(&local_successors)); | ||
| // | ||
| // TODO: If possible we should avoid recomputing this every time. I think the | ||
| // reachability information only meaningfully changes when we strip a back edge, | ||
| // so in theory we should only need to recompute this after processing a loop. | ||
| let strict_reachable_from = || flip_edges(transitive_closure(&local_successors)); | ||
|
|
||
| // Handle our simple case of only 1 entry. If there's no back edge to the entry | ||
| // we generate a `Simple` structure, otherwise we make a loop. | ||
| if entries.len() == 1 { | ||
| let entry = entries.first().unwrap(); | ||
| if !strict_reachable_from.contains_key(entry) { | ||
| let has_back_edge = local_successors | ||
| .values() | ||
| .any(|successors| successors.contains(entry)); | ||
|
|
||
|
Comment on lines
+254
to
+257
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need the full transitive reachability here, we just need to know if there's a back edge to our entry in our current set of blocks since that determines if we can create a
So that comment is calling out why we can't just compute reachability for the entire graph up front and then reuse that info for the entire relooping. The problem with that is that when we process a loop we strip back edges, which then changes reachability info (which is important for correctly processing the sequence of blocks within the loop body). The new comment is calling out that the reachability info only meaningfully changes when we strip back edges, so in theory we only need to recompute reachability after processing a loop body. Avoiding that recomputation might help performance when dealing with very large CFGs, but would also require some more careful thought about if stale reachability would cause problems later in |
||
| if !has_back_edge { | ||
| let bb = blocks | ||
| .swap_remove(entry) | ||
| .expect("Entry not present in current blocks"); | ||
|
|
@@ -295,11 +303,13 @@ impl RelooperState { | |
|
|
||
| self.relooper(new_entries, blocks, result); | ||
| } else { | ||
| self.make_loop(&strict_reachable_from, blocks, entries, result); | ||
| self.make_loop(&strict_reachable_from(), blocks, entries, result); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| let strict_reachable_from = strict_reachable_from(); | ||
|
|
||
| // Sanity check that we have entries that are in our current set of blocks. We | ||
| // may have entries that aren't present in our current blocks when we're inside | ||
| // the branch of a `Multiple`, but there must always be at least one present | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.