Skip to content
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

MatchBranchSimplification: fix equal const bool assignments #75537

Merged
merged 6 commits into from
Aug 15, 2020

Conversation

tmiasko
Copy link
Contributor

@tmiasko tmiasko commented Aug 14, 2020

The match branch simplification is applied when target blocks contain
statements that are either equal or perform a const bool assignment with
different values to the same place.

Previously, when constructing new statements, only statements from a
single block had been examined. This lead to a misoptimization when
statements are equal because the assign the same const bool value to
the same place.

Fix the issue by examining statements from both blocks when deciding on
replacement.

Additionally:

  • Copy discriminant instead of moving it since it might be necessary to use its
    value more than once.
  • Optimize when switching on copy operand

Based on #75508.

r? @oli-obk / @JulianKnodt

JulianKnodt and others added 4 commits August 13, 2020 23:51
This also explicitly checks that the types are `bool`. `try_eval_bool` also appears to just
succeed for `u8`, so this ensures that it actually is a bool before casting.
It might be necessary to use its value more than once.
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 14, 2020
@tmiasko tmiasko changed the title MatchBranchSimplification: fix equal const bools assignments MatchBranchSimplification: fix equal const bool assignments Aug 14, 2020
@tmiasko tmiasko force-pushed the match-branch-simplify branch 2 times, most recently from 621c973 to c96c5a0 Compare August 14, 2020 21:22
Copy link
Contributor

@JulianKnodt JulianKnodt left a comment

Choose a reason for hiding this comment

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

Ah woops yea this was something I overlooked when there are multiple assignments which do different things!

&& f_c.literal.ty.is_bool()
&& s_c.literal.ty.is_bool()
&& f_c.literal.try_eval_bool(tcx, param_env).is_some()
&& s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like these two stmts will always evaluate to true if the previous two did, but better safe than sorry

src/librustc_mir/transform/match_branches.rs Outdated Show resolved Hide resolved
@@ -78,7 +78,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
);
if let Some(c) = c.literal.try_eval_bool(tcx, param_env) {
let op = if c { BinOp::Eq } else { BinOp::Ne };
*rhs = Rvalue::BinaryOp(op, Operand::Move(discr), const_cmp);
*rhs = Rvalue::BinaryOp(op, Operand::Copy(discr), const_cmp);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this mirror the type that is matched in discr, rather than always be Copy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AFAIU move leaves undefined data behind and moving from it again would be undefined behaviour. At least in theory, if not currently in practice. Since we might need to use it more than once, using copy should be appropriate.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah makes sense, I wonder if this should always be done if the enum is relatively large

src/librustc_mir/transform/match_branches.rs Outdated Show resolved Hide resolved
@tmiasko tmiasko force-pushed the match-branch-simplify branch from c96c5a0 to 1fe2e29 Compare August 14, 2020 22:34
@@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
ref targets,
ref values,
..
} if targets.len() == 2 && values.len() == 1 => {
} if targets.len() == 2 && values.len() == 1 && targets[0] != targets[1] => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious, is targets[0] == targets[1] ever hit? I imagine that would be a whole different opt pass

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know.

The CfgSimplifier optimizes switch with the same targets to a goto, and then collapses goto chains and merges blocks.

Copy link
Contributor

Choose a reason for hiding this comment

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

we can make this condition an assert after the beta branch, then we have 12 weeks to find out if it's a problem :D

The match branch simplification is applied when target blocks contain
statements that are either equal or perform a const bool assignment with
different values to the same place.

Previously, when constructing new statements, only statements from a
single block had been examined. This lead to a misoptimization when
statements are equal because the assign the *same* const bool value to
the same place.

Fix the issue by examining statements from both blocks when deciding on
replacement.
@oli-obk
Copy link
Contributor

oli-obk commented Aug 15, 2020

r=me with the unsafe code replaced with a safe solution

@oli-obk
Copy link
Contributor

oli-obk commented Aug 15, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Aug 15, 2020

📌 Commit af9b9e4 has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 15, 2020
@bors
Copy link
Contributor

bors commented Aug 15, 2020

⌛ Testing commit af9b9e4 with merge b9db927...

@bors
Copy link
Contributor

bors commented Aug 15, 2020

☀️ Test successful - checks-actions, checks-azure
Approved by: oli-obk
Pushing b9db927 to master...

@cuviper cuviper added this to the 1.47.0 milestone May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants