Skip to content

Reimplement DestinationPropagation according to live ranges. #145541

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

cjgillot
Copy link
Contributor

@cjgillot cjgillot commented Aug 17, 2025

This PR reimplements DestinationPropagation as a problem of merging live-ranges of locals. We merge locals that have disjoint live-ranges. This allows merging several locals in the same round by updating live range information.

Live ranges are mainly computed using the MaybeLiveLocals analysis. The subtlety is that we split each statement and terminator in 2 positions. The first position is the regular statement. The second position is a shadow, which is always more live. It encodes partial writes and dead writes as a local being live for half a statement. This half statement ensures that writes conflict with another local's writes and regular liveness.

r? @Amanieu

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 17, 2025
@rust-log-analyzer

This comment was marked as outdated.

@cjgillot cjgillot force-pushed the dest-prop-live-range branch from 8402e97 to da2cabf Compare August 17, 2025 22:58
@rust-log-analyzer

This comment was marked as outdated.

@cjgillot cjgillot force-pushed the dest-prop-live-range branch from da2cabf to d0d5f20 Compare August 17, 2025 23:09
@cjgillot
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Aug 17, 2025
[EXPERIMENT] Reimplement DestinationPropagation according to live ranges.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 17, 2025
@rust-bors
Copy link

rust-bors bot commented Aug 17, 2025

⌛ Trying commit d0d5f20 with merge 9d4b3bf

To cancel the try build, run the command @bors try cancel.

1 similar comment
@rust-bors

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Aug 18, 2025

☀️ Try build successful (CI)
Build commit: 9d4b3bf (9d4b3bf23319cc25ade991de3dea06e46b155552, parent: 425a9c0a0e365c0b8c6cfd00c2ded83a73bed9a0)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (9d4b3bf): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

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

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.6% [0.2%, 1.2%] 11
Regressions ❌
(secondary)
0.6% [0.2%, 1.6%] 41
Improvements ✅
(primary)
-0.6% [-2.3%, -0.2%] 16
Improvements ✅
(secondary)
-0.8% [-2.4%, -0.0%] 63
All ❌✅ (primary) -0.1% [-2.3%, 1.2%] 27

Max RSS (memory usage)

Results (primary -2.8%, secondary -2.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
4.1% [4.1%, 4.1%] 1
Regressions ❌
(secondary)
2.2% [1.9%, 2.5%] 2
Improvements ✅
(primary)
-5.1% [-7.6%, -1.2%] 3
Improvements ✅
(secondary)
-3.6% [-4.9%, -1.0%] 7
All ❌✅ (primary) -2.8% [-7.6%, 4.1%] 4

Cycles

Results (primary -2.6%, secondary -7.5%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.3% [1.3%, 3.9%] 4
Improvements ✅
(primary)
-2.6% [-2.6%, -2.6%] 1
Improvements ✅
(secondary)
-13.1% [-23.5%, -3.4%] 7
All ❌✅ (primary) -2.6% [-2.6%, -2.6%] 1

Binary size

Results (primary -0.1%, secondary -0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.0%, 0.3%] 14
Regressions ❌
(secondary)
0.2% [0.0%, 0.6%] 44
Improvements ✅
(primary)
-0.1% [-0.9%, -0.0%] 40
Improvements ✅
(secondary)
-0.6% [-2.0%, -0.0%] 22
All ❌✅ (primary) -0.1% [-0.9%, 0.3%] 54

Bootstrap: 470.373s -> 469.514s (-0.18%)
Artifact size: 377.75 MiB -> 374.67 MiB (-0.82%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Aug 18, 2025
@cjgillot cjgillot force-pushed the dest-prop-live-range branch 2 times, most recently from 139b66c to da90180 Compare August 19, 2025 10:49
Comment on lines +608 to +603
// We also ensure that operands read by terminators conflict with writes by that terminator.
// For instance a function call may read args after having written to the destination.
Copy link
Member

Choose a reason for hiding this comment

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

This is actually stricter than necessary. It's only Move operands that conflict with the destination place because they effectively "donate" the place to the callee. Copy and Const operands don't conflict because they are copied to a new place before the call.

I also don't think any other terminators have this issue, it is specific to Call terminators (#71117).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have 5 terminators that write to memory: Call, TailCall, Drop, Yield, InlineAsm. Yield terminators are forbidden at this stage.

However, InlineAsm has this issue too. And for both copies and moves.

About the Copy vs Move, I wonder what's the proper solution:

  • match on terminators? -> I'd rather avoid if I can
  • how to implement move-to-copy conversion later to allow more dest-prop
    Could we push this question to a follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

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

I'm pretty sure the move behavior only applies to Call and not other terminators. I've posted a proposal to clarify this in MIR.

});
}
#[derive(Debug)]
struct RelevantLocals {
Copy link
Member

Choose a reason for hiding this comment

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

The logic around tracking candidates could be vastly simplified by using a disjoint-set data structure, but this can be done later in a separate PR.

@cjgillot cjgillot force-pushed the dest-prop-live-range branch from da90180 to 35399f0 Compare August 20, 2025 23:42
@cjgillot
Copy link
Contributor Author

The latest force-push removes the useless commit from the other PR to simplify the history.

This analysis is strictly less powerful than the current algorithm. This PR forbids to merge locals that are live at the same point because of extra reads. I'm not sure it's important, but this makes DestinationPropagation and GVN adversarial in some ways. GVN attempts to make SSA locals with the longest live range possible. DestinationPropagation will prefer clean moves from a local to another.

@cjgillot cjgillot changed the title [EXPERIMENT] Reimplement DestinationPropagation according to live ranges. Reimplement DestinationPropagation according to live ranges. Aug 21, 2025
@cjgillot cjgillot marked this pull request as ready for review August 21, 2025 00:25
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 21, 2025
@rustbot
Copy link
Collaborator

rustbot commented Aug 21, 2025

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@cjgillot
Copy link
Contributor Author

cc @oli-obk as you were involved in reviewing the other PR.

@Amanieu
Copy link
Member

Amanieu commented Aug 21, 2025

This analysis is strictly less powerful than the current algorithm. This PR forbids to merge locals that are live at the same point because of extra reads. I'm not sure it's important, but this makes DestinationPropagation and GVN adversarial in some ways. GVN attempts to make SSA locals with the longest live range possible. DestinationPropagation will prefer clean moves from a local to another.

I'm struggling to picture an example that was accepted by the previous algorithm but not by this one. Could you give an example?

@cjgillot
Copy link
Contributor Author

For instance :

_1 = const 5;
_0 = copy _1;
_2 = foo(copy _1) -> bb

Where we may want to merge _0 and _1.

// Just extend the first range.
*first_start = point;
} else {
self.map.insert(0, (point, point));
Copy link
Member

Choose a reason for hiding this comment

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

It's unfortunate that this is O(n^2). It is possible to make this O(n) by building the intervals in reverse order and then reversing the whole array at the end. Actually even the final reversal isn't strictly needed if you take the reversed order into account when unioning rows and checking for disjointness.

@cjgillot cjgillot force-pushed the dest-prop-live-range branch from 35399f0 to 2b59dab Compare August 22, 2025 21:27
@rustbot
Copy link
Collaborator

rustbot commented Aug 22, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@bors
Copy link
Collaborator

bors commented Aug 23, 2025

☔ The latest upstream changes (presumably #145773) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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.

6 participants