Skip to content

MatchBranchSimplification: fix equal const bool assignments - #75537

Merged
bors merged 6 commits into
rust-lang:masterfrom
tmiasko:match-branch-simplify
Aug 15, 2020
Merged

bors merged 6 commits into
rust-lang:masterfrom
tmiasko:match-branch-simplify

Conversation

@tmiasko

@tmiasko tmiasko commented Aug 14, 2020 •

Copy link
Copy Markdown
Contributor

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

@JulianKnodt JulianKnodt left a comment

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.

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

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.

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

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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

@tmiasko
tmiasko force-pushed the match-branch-simplify branch from c96c5a0 to 1fe2e29 Compare August 14, 2020 22:34
ref values,
..
} if targets.len() == 2 && values.len() == 1 => {
} if targets.len() == 2 && values.len() == 1 && targets[0] != targets[1] => {

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.

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

Copy link
Copy Markdown
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
Copy Markdown
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.
Comment thread src/librustc_index/vec.rs Resolved
@oli-obk

oli-obk commented Aug 15, 2020

Copy link
Copy Markdown
Contributor

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

@oli-obk

oli-obk commented Aug 15, 2020

Copy link
Copy Markdown
Contributor

@bors r+

@bors

bors commented Aug 15, 2020

Copy link
Copy Markdown
Collaborator

📌 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

bors commented Aug 15, 2020

Copy link
Copy Markdown
Collaborator

⌛ Testing commit af9b9e4 with merge b9db927...

@bors

bors commented Aug 15, 2020

Copy link
Copy Markdown
Collaborator

☀️ 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