-
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
optimizing Use expressions inside if condition #111644
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @petrochenkov (or someone else) soon. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
This comment has been minimized.
This comment has been minimized.
r? rust-lang/compiler |
Could you add a reduced version of the code in #111583 as a mir-opt test? In the I'm a bit worried by this change. cc @dingxiangfei2009 as have better knowledge of MIR scoping than I |
Thanks for the review @cjgillot. I think the change is sound based on how As for the UI change, the code is basically: pub fn foo(){
let x;
if true && {x = 4; true} && x == 4 {}
} which currently does not compile (x is possibly uninitialized). Now consider this equivalent function: pub fn bar(){
let x;
if true {
if {x = 4; true} && x == 4 {}
}
} This one does compile today but if you transform it to the equivalent function Please correct me if I'm wrong in any of that. I could be missing something. As for the test cases, I would add them if I'm on the right track. |
@azizghuloum Thank you for your PR! I would like to supply additional information for the review. The purpose of By bypassing the There are two interesting questions remained. One is how shall we also admin the program in #111644 (comment) and another is why the performance degradation happens. I would need some extra time on the investigation. I will be right back. |
Note to self. The From reading the code, it seemed like having a "chained" So, strangely, this compiles: #![feature(let_chains)]
pub fn foo() {
let x;
if let _t = 0 && true && {x = 4; true} && x == 4 {}
} while this doesn't: pub fn foo() {
let x;
if true && {x = 4; true} && x == 4 {}
} which is leading me to think that there is more that is broken than it seemed at first. |
Working on another solution which does not affect lifetimes... testing now. |
@azizghuloum I digged deeper into the code today and I would like to say that I am glad that you have kept this PR open. I believe it is still safe to unwrap the cc @cjgillot Also, the reason that employing |
@azizghuloum like I asked in #111752, could you add a test for this new behaviour in the mir-opt/built directory? There are examples in that directory. That test should involve each term in the logical expression to have stuff to drop ( This PR makes new code compile, so we'll need a signoff from t-lang. |
@cjgillot what's a "signoff from t-lang"? Sorry, new here. |
Did add the test, and as I expected, there are now two drop calls for each |
Greetings again, I have fixed PR #111725 to
Can we review that one and close this PR please? @cjgillot @dingxiangfei2009 |
Replaced by #111725 |
…=cjgillot Lower `Or` pattern without allocating place cc `@azizghuloum` `@cjgillot` Related to rust-lang#111583 and rust-lang#111644 While reviewing rust-lang#111644, it occurs to me that while we directly lower conjunctive predicates, which are connected with `&&`, into the desirable control flow, today we don't directly lower the disjunctive predicates, which are connected with `||`, in the similar fashion. Instead, we allocate a place for the boolean temporary to hold the result of evaluating the `||` expression. Usually I would expect optimization at later stages to "inline" the evaluation of boolean predicates into simple CFG, but rust-lang#111583 is an example where `&&` is failing to be optimized away and the assembly shows that both the expensive operands are evaluated. Therefore, I would like to make a small change to make the CFG a bit more straight-forward without invoking the `as_temp` machinery, and plus avoid allocating the place to hold the boolean result as well.
First time contributor here.
While debugging the issue, I noticed that the HIR tree for the "slow" part contained
Use
expressions that were not handled in any special way during lowering to MIR, and thus introduced a temporary variable and lead to the performance degradation reported.The change of course affects how MIR is generated, and thus affects a number of tests. In particular, it makes one (ui) test pass when it used to compile with error. The other tests affected, according to my (shallow) analysis, look correct.
Feedback appreciated.
Fixes #111583