Skip to content

Avoid loop_match self-assignment in MIR lowering#155186

Open
cijiugechu wants to merge 1 commit intorust-lang:mainfrom
cijiugechu:fix/loop-match-no-self-assign
Open

Avoid loop_match self-assignment in MIR lowering#155186
cijiugechu wants to merge 1 commit intorust-lang:mainfrom
cijiugechu:fix/loop-match-no-self-assign

Conversation

@cijiugechu
Copy link
Copy Markdown
Contributor

@cijiugechu cijiugechu commented Apr 12, 2026

Transform

bb2: {
        PlaceMention(_1);
        _1 = copy _1;
        goto -> bb7;
    }

to

bb2: {
        PlaceMention(_1);
        _4 = copy _1;
        _1 = copy _4;
        goto -> bb7;
    }

Closes #143806

Previous MIR
fn helper() -> u8 {
    let mut _0: u8;
    let mut _1: u8;
    let mut _2: !;
    let mut _3: !;
    scope 1 {
        debug state => _1;
    }

    bb0: {
        StorageLive(_1);
        _1 = const 0_u8;
        FakeRead(ForLet(None), _1);
        StorageLive(_2);
        goto -> bb1;
    }

    bb1: {
        falseUnwind -> [real: bb2, unwind: bb11];
    }

    bb2: {
        PlaceMention(_1);
        _1 = copy _1;
        goto -> bb7;
    }

    bb3: {
        FakeRead(ForMatchedPlace(None), _1);
        unreachable;
    }

    bb4: {
        unreachable;
    }

    bb5: {
        goto -> bb6;
    }

    bb6: {
        goto -> bb8;
    }

    bb7: {
        goto -> bb8;
    }

    bb8: {
        goto -> bb1;
    }

    bb9: {
        unreachable;
    }

    bb10: {
        StorageDead(_2);
        StorageDead(_1);
        return;
    }

    bb11 (cleanup): {
        resume;
    }
}
Current MIR
fn helper() -> u8 {
    let mut _0: u8;
    let mut _1: u8;
    let mut _2: !;
    let mut _3: !;
    let mut _4: u8;
    scope 1 {
        debug state => _1;
    }

    bb0: {
        StorageLive(_1);
        _1 = const 0_u8;
        FakeRead(ForLet(None), _1);
        StorageLive(_2);
        goto -> bb1;
    }

    bb1: {
        falseUnwind -> [real: bb2, unwind: bb11];
    }

    bb2: {
        PlaceMention(_1);
        _4 = copy _1;
        _1 = copy _4;
        goto -> bb7;
    }

    bb3: {
        FakeRead(ForMatchedPlace(None), _1);
        unreachable;
    }

    bb4: {
        unreachable;
    }

    bb5: {
        goto -> bb6;
    }

    bb6: {
        goto -> bb8;
    }

    bb7: {
        goto -> bb8;
    }

    bb8: {
        goto -> bb1;
    }

    bb9: {
        unreachable;
    }

    bb10: {
        StorageDead(_2);
        StorageDead(_1);
        return;
    }

    bb11 (cleanup): {
        resume;
    }
}

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 12, 2026

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@rustbot rustbot added 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. labels Apr 12, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 12, 2026

r? @jdonszelmann

rustbot has assigned @jdonszelmann.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 11 candidates

@folkertdev folkertdev added the F-loop_match when you match up with someone and they really throw you for a loop label Apr 12, 2026
@folkertdev
Copy link
Copy Markdown
Contributor

Just conceptually, would it not be better to remove the assignment completely? Or does that not work?

I've previously tried to change the code so that the assignment does not get introduced, but that did not work out (it would, from memory, require overhauling a whole bunch of code).

@cijiugechu
Copy link
Copy Markdown
Contributor Author

Just conceptually, would it not be better to remove the assignment completely? Or does that not work?

I've previously tried to change the code so that the assignment does not get introduced, but that did not work out (it would, from memory, require overhauling a whole bunch of code).

I did consider this approach at first, but I was worried that it might have a fairly significant impact on MIR semantics. Once Rvalue::Use(Operand::Copy(_1)) is removed, it could also affect borrowck’s analysis, so in the end I chose the more conservative approach.

@cijiugechu
Copy link
Copy Markdown
Contributor Author

Additionally, I also considered the performance impact. I compared the LLVM IR generated by the compiler for loop_match before and after the change, and they were the same, so there should not bring performance regression.

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

Labels

F-loop_match when you match up with someone and they really throw you for a loop 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.

ICE: loop match: broken mir encountered 'Assign' statement with overlapping memory

4 participants