-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
[mir] or-patterns duplicate the same branch #75439
Comments
This comment has been minimized.
This comment has been minimized.
Was this resolved by #75537? I believe that this would actually match on it, just because all the statements are the same |
I've just checked. The MIR isn't improved with #75537 . |
Ah woops yea I can't count, this has 3 branches not 2, which is the only permitted number of branches being optimized currently. |
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
Add test for checking duplicated branch or-patterns This adds a regression test for checking `or-patterns` in MIR as shown in rust-lang#75439. This doesn't introduce a fix as I'm not sure where it would go(I suspect maybe here: src/librustc_mir_build/build/matches/mod.rs), and I'm not particularly able to fix it. cc: @lzutao
This might be a suitable way to solve the same problem, but I'm not really sure:
i.e. combine them when building the MIR in the first place. |
I was able to repro this today (85e355e). |
@rustbot claim I'm not sure if I'll be able to fix this, but I spent some time this weekend studying lowering to MIR and tried to understand the issue here. First of all, the inefficiency here exists even in the final LLVM (with
Now, I looked at why these duplicate blocks are generated, in MIR. I believe the reason is the same as the reason why we generate duplicate blocks in this simpler program: pub fn test(dwords: [u32; 2]) {
match dwords {
[0 | 1, _a] => (),
_ => (),
}
} LLVM is able to optimize the duplicate blocks in this program, but in MIR we still have duplication very similar to the original repro:
Namely I think if we could generate better MIR for this simpler program that would also fix the problem with the original repro. Here's the original MIR for this program (before any passes):
The reason for this duplication is: originally for this program, in the first arm, we have a candidate with two "match pairs": the or pattern, and the binding ( When generating MIR for a subcandidate, we first generate a block just to be able to chain blocks of arms for borrow checking (using "false eges"). This is why we create Then in those new blocks (
for all alternatives of the or pattern. (The intermediate blocks I think it's possible to generate better code here when the subcandidates (transitively) don't have any bindings, ascriptions, and guards (I don't understand the guards in details yet so I don't know if there are room for optimization also). In those cases, before generating MIR for the subcandidates, we create a "target" block where we will generate the binding code. Then create branches for each subcandidate as we do today (with the false edges), but these subcandidates jump to the "target" block instead of to fresh blocks. The target block will then have the code for the binding in the parent candidate. In other words we generate one block for the parent candidate's bindings instead of introducing the bindings it in each subcandidate. I actually have an implementation of this, but it causes linker errors when compiling libraries. I'll submit a PR once it's working. One problem is the idea is the check "do the subcandidates have any bindings, ascriptions, or guards" requires traversing the entire candidate tree. I don't know if we can implement this more efficiently somehow. The MIR (before passes) with this implementation would look like:
Because we no longer have duplicate blocks for or pattern alternatives the issue is fixed. |
It looks like you already figured out most of this, but here some notes I wrote from the last time I went through some of that code: rust-lang/rustc-dev-guide#943 |
Thanks @mark-i-m, that's very helpful. Update: I figured this out and have a working prototype. On the way I was also able to come up with examples where the duplication is much larger then the original repro or my simpler repro above, which my code fixes. I'm hoping to submit a PR this weekend. |
Update: my patch works mostly fine. There are two failures in the test suite, both are caused by disappeared In the meantime, if anyone knows about the question I linked above, that would be very helpful. |
Isn't that already what we do in |
since this is reviving a Even if it's not still happening, it might be good to close the issue and start a new one so it's more easily tracked (and doesn't ping people who aren't working on it actively anymore) |
I did check, it's still duplicated |
This fixed by #123067. cc @Nadrieril @rustbot label +E-needs-test |
Amazing, thanks for figuring this out |
The fixing PR already updates the test for this issue so this can be closed |
Consider this snippet:
The or-pattern
0 | FF
has this MIR:While
bb6
andbb7
points to the same branch:I would expect the or-pattern points the same branch.
The text was updated successfully, but these errors were encountered: