Transforms match into an assignment statement by DianQK · Pull Request #120614 ·...
source link: https://github.com/rust-lang/rust/pull/120614
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Transforms match into an assignment statement #120614
Conversation
Member
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
This comment has been minimized.
Member
This comment has been minimized.
Contributor
☀️ Try build successful - checks-actions |
This comment has been minimized.
Collaborator
Finished benchmarking commit (eea65f2): comparison URL. Overall result: no relevant changes - no action neededBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)Results CyclesResults Binary sizeResults Bootstrap: 659.957s -> 661.541s (0.24%) |
removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label
Collaborator
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
compiler/rustc_mir_transform/src/match_branches.rs
Outdated Show resolved
} |
||
trait SimplifyMatch<'tcx> { |
||
fn simplify( |
Contributor
Could you comment what this function does?
Member
Author
Done.
compiler/rustc_mir_transform/src/match_branches.rs
Outdated Show resolved
let def_id = body.source.def_id(); |
||
let param_env = tcx.param_env_reveal_all_normalized(def_id); |
||
let bbs = body.basic_blocks.as_mut(); |
Contributor
Calling as_mut()
clears the CFG caches unconditionally. Is there a way to delay this invalidation?
Member
Author
I submitted a separate commit. I invalidate the cache only after modifying the CFG. If the cache is used later in a loop, we need to invalidate it after each modification.
Member
Author
With MirPatch
we don't need to worry about this.
/// goto -> bb5; |
||
/// } |
||
/// ``` |
||
impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { |
Contributor
IIUC, this transform is a strict superset of SimplifyToIf
, isn't it? Can we only keep this one?
Member
Author
Most of their code can't be shared, and if they were put together, I'd be worried that it would be difficult to maintain later. A major difference is that the otherwise target of SimplifyToIf
is reachable, while SimplifyToExp
is unreachable.
Contributor
☔ The latest upstream changes (presumably #121036) made this pull request unmergeable. Please resolve the merge conflicts. |
added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
labels
Member
Author
Sorry for my late reply. |
This comment has been minimized.
Contributor
💔 Test failed - checks-actions |
added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
labels
This comment has been minimized.
Member
Author
Rebased. :> |
Member
@bors r=cjgillot |
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
Contributor
☀️ Test successful - checks-actions |
Collaborator
Finished benchmarking commit (211518e): comparison URL. Overall result: ❌ regressions - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)Results CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeResults Bootstrap: 669.664s -> 668.886s (-0.12%) |
let (from, first, second) = bbs.pick3_mut(bb_idx, first, second); |
||
fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool { |
||
l.try_to_int(l.size()).unwrap() |
||
== ScalarInt::try_from_uint(r, size).unwrap().try_to_int(size).unwrap() |
Member
What is the point of doing the comparison in such a complicated way? Why turn r
into a ScalarInt
and then back into a i128
?
Member
Author
Because SwitchTargets
only saves the value of the corresponding bit value by u128
, it lacks information on bit-width and sign.
Member
It doesn't need the sign, as I said: ==
is sign-independent, so we can figure out the switch target without knowing the sign. And it has the width, it is determined by the type of the match operand.
Member
Author
Ah, you're right. This code is used to compare signed integers of different widths, such as i8
and i16
. We must add additional conversions for this scenario.
Hmm, it's been just a month, and I have to carefully review the code to respond correctly. It seems I indeed wrote some hard-to-understand code. :>
I'll add some comments. I should also move the unsigned comparison to the front, as I expect this might make the code a bit faster.
&& int_equal(s, second_val, discr_size)) |
||
|| (Some(f) == ScalarInt::try_from_uint(first_val, f.size()) |
||
&& Some(s) |
||
== ScalarInt::try_from_uint(second_val, s.size())) => |
This is very strange. ==
is sign-independent, so I don't understand why both cases need to be considered here. Furthermore, if the sign mattered, then surely it makes no sense to check they_are_equal_signed || they_are_equal_unsigned
; instead you have to check if they_are_signed { they_are_equal_signed } else { they_are_equal_unsigned }
. Finally, f_c.const_.ty().is_signed() || discr_ty.is_signed()
sounds like you are mixing signed and unsigned values (as in, LHS and RHS can have different sign), which should never happen.
What is going on here?
Member
Author
This is used to handle conversions such as from enum(u32)
to i32
or from enum(i32)
to u32
:
Aha... I have no idea what this means. ;)
But it makes no sense to compare things twice here. ==
is entirely based on being equal bitwise, so the sign doesn't matter.
Member
Author
Same as above (different width), corresponding test case:
But you are comparing both signed and unsigned representation completely disregarding whether the value is actually signed or unsigned. It sounds like you want two cases
- value is signed; then convert everything to
i128
(with sign extension, e.g. viatry_to_int
) and compare there - value is unsigned; the convert everything to
u128
and compare there
But currently you're interpreting the number both ways and then checking if either comparison succeeds. It seems to me that can sometimes lead to blatantly wrong results, e.g. when two numbers are equal unsigned but different after sign extension, and they are actually signed -- you code will treat them as equal, I think?
Member
Author
Ah, I'm fixing it right now.
Member
Author
Fixed in #124122, thanks for pointing it out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Successfully merging this pull request may close these issues.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK