Skip to content

MIR move elimination [1/6]: MIR preparation - #163335

Open
Amanieu wants to merge 5 commits into
rust-lang:mainfrom
Amanieu:move-elimination/mir-preparation
Open

Amanieu wants to merge 5 commits into
rust-lang:mainfrom
Amanieu:move-elimination/mir-preparation

Conversation

@Amanieu

@Amanieu Amanieu commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

This PR contains preparatory work for supporting the new MIR semantics from rust-lang/rfcs#3943.

  • Adds -Zmir-move-elimination which both opts-in to the new semantics and enables the new optimization pass.
  • Updates doc comments with the new semantics of MIR under the flag.
  • Adds the StorageAlloc MIR statement. This is used by the MIR inliner when it needs to borrow a destination place that hasn't been initialized.
  • Fixes several cases where ZST unit values are not properly initialized.
  • Fixes async drop elaboration which incorrectly used a move instead of a copy, leading to a use-after-move.

r? tmiasko

@rustbot

rustbot commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to constck

cc @fee1-dead

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

This PR changes MIR

cc @oli-obk, @RalfJung, @JakobDegen, @vakaras

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

This PR changes rustc_public

cc @oli-obk, @celinval, @ouz-a, @makai410

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 25, 2026
@rustbot rustbot added T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 25, 2026
@Amanieu

Amanieu commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

LLM disclosure: this PR is in large part the result of an LLM-assisted audit of all existing MIR transformations against the new MIR semantics as implemented in Miri in #163340. LLMs were also used to generate the boilerplate for the MIR tests, but each test was manually reviewed and adjusted before committing.

Comment thread compiler/rustc_borrowck/src/def_use.rs Outdated
@oli-obk oli-obk added the llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. label Sep 25, 2026
Comment thread compiler/rustc_session/src/options.rs
Comment thread compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs Outdated
Comment thread compiler/rustc_borrowck/src/type_check/mod.rs Outdated
Comment thread compiler/rustc_borrowck/src/def_use.rs Outdated
Comment thread compiler/rustc_borrowck/src/lib.rs Outdated
Comment thread compiler/rustc_middle/src/mir/syntax.rs
@tmiasko

tmiasko commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

We started with a single pull request with 65 files changed, and now ended up with multiple "smaller" pull requests, where the first one has 115 files changed. This is not exactly what I expected. Could you move some parts to smaller pull requests still. For example parts of "Fix missing ZST initialization in MIR passes" which don't depend on -Zmir-move-elimination at all.

@Amanieu

Amanieu commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

I'm currently working to make none of the changes in this PR depend on -Zmir-move-elimination. That way we always have MIR that works with both the old and new semantics, and we don't need to make this a target modifier.

The main concern is that this means restricting RemoveZsts to never remove assignments, which is causing a lot of churn in the mir-opt test snapshots. Most of these assignments are later removed by DSE, but most mir-opt tests only run a single MIR pass.

I will then move all of the ZST-related changes to a separate PR since they no longer depend on the flag.

@Amanieu

Amanieu commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

I've moved the ZST-related changes to #163359.

We started with a single pull request with 65 files changed, and now ended up with multiple "smaller" pull requests, where the first one has 115 files changed. This is not exactly what I expected.

Most of the difference come from this preparation work which adjusts the rest of the compiler to work with the new semantics, which ends up touching a lot of tests. The actual compiler code changes are not that big.

@rust-log-analyzer

This comment has been minimized.

@Amanieu
Amanieu force-pushed the move-elimination/mir-preparation branch from 43c741c to 7d28b47 Compare September 25, 2026 23:20
@Amanieu

Amanieu commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

I moved the MIR validity changes to the Miri PR.

(!debuginfo_locals.contains(place.local)).then_some(**place)
}
StatementKind::FakeRead(_)
| StatementKind::StorageAlloc(_)

@tmiasko tmiasko Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do you know a specific reason why StorageAlloc cannot be removed? (If yes, a comment and a test case would be nice to have).

View changes since the review

Comment on lines 195 to +230
@@ -226,6 +227,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage {
StatementKind::SetDiscriminant { place, .. } => {
state.gen_(place.local);
}
StatementKind::StorageAlloc(local) => state.gen_(*local),

@tmiasko tmiasko Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we turn those StorageAlloc arms into bug!?

View changes since the review

Comment on lines +330 to +338
StatementKind::StorageAlloc(l) => {
if let Some(final_locals) = self.replacements.place_fragments(l.into()) {
for (_, _, fl) in final_locals {
self.patch.add_statement(location, StatementKind::StorageAlloc(fl));
}
statement.make_nop(true);
}
return;
}

@tmiasko tmiasko Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add a test case.

View changes since the review

Comment on lines 690 to +697
pub(crate) fn remove_unused_storage_annotations<'tcx>(&self, body: &mut Body<'tcx>) {
for data in body.basic_blocks.as_mut_preserves_cfg() {
// Remove unnecessary StorageLive and StorageDead annotations.
// Remove storage statements for unused locals.
for statement in data.statements.iter_mut() {
let keep_statement = match &statement.kind {
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
self.locals.contains(*local)
}
StatementKind::StorageLive(local)
| StatementKind::StorageDead(local)
| StatementKind::StorageAlloc(local) => self.locals.contains(*local),

@tmiasko tmiasko Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add a test case.

View changes since the review

Comment on lines -170 to +171
if !context.is_use() {
// StorageAlloc requires the local to be live.
if !context.is_use() && context != PlaceContext::NonUse(NonUseContext::StorageAlloc) {

@tmiasko tmiasko Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add a test case.

View changes since the review

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llm-assisted An LLM-assisted PR as defined by the LLM policy. Requires ahead-of-time consent by assignee. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants