Skip to content
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

Use reverse postorder in non_ssa_locals #96601

Merged
merged 1 commit into from
May 3, 2022
Merged

Conversation

tmiasko
Copy link
Contributor

@tmiasko tmiasko commented May 1, 2022

The reverse postorder, unlike preorder, is now cached inside the MIR
body. Code generation uses reverse postorder anyway, so it might be
a small perf improvement to use it here as well.

The reverse postorder, unlike preorder, is now cached inside the MIR
body. Code generation uses reverse postorder anyway, so it might be
a small perf improvement to use it here as well.
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 1, 2022
@rust-highfive
Copy link
Collaborator

r? @davidtwco

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 1, 2022
@tmiasko
Copy link
Contributor Author

tmiasko commented May 1, 2022

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label May 1, 2022
@bors
Copy link
Contributor

bors commented May 1, 2022

⌛ Trying commit fa41852 with merge 204cd52d1e796574f64ace5276cb3a794e73585f...

@bors
Copy link
Contributor

bors commented May 1, 2022

☀️ Try build successful - checks-actions
Build commit: 204cd52d1e796574f64ace5276cb3a794e73585f (204cd52d1e796574f64ace5276cb3a794e73585f)

@rust-timer
Copy link
Collaborator

Queued 204cd52d1e796574f64ace5276cb3a794e73585f with parent f75d884, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (204cd52d1e796574f64ace5276cb3a794e73585f): comparison url.

Summary:

  • Primary benchmarks: 🎉 relevant improvement found
  • Secondary benchmarks: no relevant changes found
Regressions 😿
(primary)
Regressions 😿
(secondary)
Improvements 🎉
(primary)
Improvements 🎉
(secondary)
All 😿 🎉
(primary)
count1 0 0 1 0 1
mean2 N/A N/A -0.3% N/A -0.3%
max N/A N/A -0.3% N/A -0.3%

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 may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf -perf-regression

Footnotes

  1. number of relevant changes

  2. the arithmetic mean of the percent change

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label May 1, 2022
@nagisa
Copy link
Member

nagisa commented May 1, 2022

Does iterating in this order retain the benefits of pre-order as described in #85741?

@tmiasko
Copy link
Contributor Author

tmiasko commented May 2, 2022

Does iterating in this order retain the benefits of pre-order as described in #85741?

Yes. If x dominates y, then in any depth first walk of the control flow graph, x must be before y in a pre-order, and x must be before y in reverse post-order.

@davidtwco
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented May 3, 2022

📌 Commit fa41852 has been approved by davidtwco

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 3, 2022
@bors
Copy link
Contributor

bors commented May 3, 2022

⌛ Testing commit fa41852 with merge 9aeba99dc26b95ab9a9d737df6352a197e436845...

@rust-log-analyzer
Copy link
Collaborator

A job failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

@bors
Copy link
Contributor

bors commented May 3, 2022

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 3, 2022
@tmiasko
Copy link
Contributor Author

tmiasko commented May 3, 2022

@bors retry spurious network error

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 3, 2022
@bors
Copy link
Contributor

bors commented May 3, 2022

⌛ Testing commit fa41852 with merge fe21c30fb9b85db46cd807a0a345bb06bee90882...

@bors
Copy link
Contributor

bors commented May 3, 2022

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 3, 2022
@tmiasko
Copy link
Contributor Author

tmiasko commented May 3, 2022

@bors retry #93784

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 3, 2022
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
.......... (60/63)
..        (63/63)


/checkout/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml search-tab-selection-if-current-is-empty... FAILED
[ERROR] (line 6) TimeoutError: waiting for selector "#titles" failed: timeout 30000ms exceeded: for command `wait-for: "#titles"`
Build completed unsuccessfully in 0:00:41

@bors
Copy link
Contributor

bors commented May 3, 2022

⌛ Testing commit fa41852 with merge e1df625...

@bors
Copy link
Contributor

bors commented May 3, 2022

☀️ Test successful - checks-actions
Approved by: davidtwco
Pushing e1df625 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 3, 2022
@bors bors merged commit e1df625 into rust-lang:master May 3, 2022
@rustbot rustbot added this to the 1.62.0 milestone May 3, 2022
@tmiasko tmiasko deleted the ssa-rpo branch May 3, 2022 15:11
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (e1df625): comparison url.

Summary: This benchmark run did not return any relevant results.

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

Comment on lines 42 to 46
// If there exists a local definition that dominates all uses of that local,
// the definition should be visited first. Traverse blocks in preorder which
// the definition should be visited first. Traverse blocks in an order that
// is a topological sort of dominance partial order.
for (bb, data) in traversal::preorder(&mir) {
for (bb, data) in traversal::reverse_postorder(&mir) {
analyzer.visit_basic_block_data(bb, data);
Copy link
Member

@eddyb eddyb Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, a bit surprised this was using preorder. I thought it was RPO since that's the correct def-before-use order (but I guess we have to check for dominance anyway so this can't go wrong just be unnecessarily conservative?).

EDIT: ah I see, it went through these steps:

Would it make sense to force visit_body to use RPO? Or have two forms, visit_body_unordered and visit_body_rpo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that preorder and reverse postorder give identical end results, since either visits a definition before a use, when the definition dominates the use (and the order is irrelevant otherwise).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: you can mostly ignore the rant below, it's me reasoning about RPO to myself, really


Hmm, I think it depends on what kind of "definition" we're talking about - I think I overapproximated what RPO actually did, and how it's stronger than just giving you "dominator before dominated".

I guess that implies a fun iteration algorithm like this:

fn visit_block(&mut self, bb: Block) {
    if self.visited[bb] { return; }
    if let Some(dom_bb) = self.doms[bb] {
        self.visit_block(dom_bb);
    }

    // ... guaranteed to get here only once and *after* all dominators ...
}

More seriously though, I guess RPO is important in SSA for merges (let's ignore cycles for now):

  S(tart)
 / \
a   b
 \ /
  M(erge)
flatten dedup
(keep first)
dedup
(keep last)
preorder S->{a->M, b->M} SaMbM SaMb SabM
reverse (per-column) MbMaS bMaS MbaS
postorder {M<-a, M<-b}<-S MaMbS MabS aMbS
reverse (per-column) SbMaM SbaM SbMa

And RPO is usually the reversed "dedup (keep first)" postorder, which ends up as SbaM (though siblings can be reversed in the initial postorder visit to get SabM if that's aesthetically preferred for e.g. an IR dump - we should do this for --emit=mir IMO).

What we're looking for in this example is S->{a,b}->M which is a bit like structured control-flow, and for SSA in particular it allows seeing all the definitions of φ nodes (or "BB args" values etc.) before a merge (not sure if this logic works for backedges, but it partially might?).
In MIR we don't have φ nodes but we still want to see all "sources" of a merge before the merge for dataflow algorithms, for pretty much the same reason SSA IRs use φ/BB args, the difference being that a fixpoint dataflow algorithm is only slowed down by the suboptimal order (whereas SSA IR passes may have bigger issues with lacking definitions used by φ nodes).

Also, you may have noticed the above table that the preorder "dedup (keep last)" is SabM without any reversals (but "keep last" is more expensive computationally, since we tend not to have the "flatten" form at all but instead skip visiting eagerly, which naturally results in "keep first").

So really what "RPO" does is a more efficient way to get "preorder but keep only the last visit instead of the usual first" (isomorphic up to sibling order, but I think you can get them perfectly equal if you make the "aesthetic fix" to RPO).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants