-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Optimize out nop-matches #66234
Comments
Ideally we'd not even limit ourselves to going from an enum to the same enum, but moving from one enum to another as long as the layouts match up. Though that may require the insertion of a |
This could apply to structs as well. For example, in: struct Foo {
a: usize,
b: bool
}
fn bar(val: Foo) -> Foo {
let new = Foo {
a: val.a,
b: val.b
};
new
}
|
Does this issue have something to do with the performance problem described in #37939? |
[WIP] [mir-opt] asking `?`s in a more optimized fashion This PR works towards #66234 by providing two optimization passes meant to run in sequence: - `SimplifyArmIdentity` which transforms something like: ```rust _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY ); ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP; discriminant(_LOCAL_0) = VAR_IDX; ``` into: ```rust _LOCAL_0 = move _LOCAL_1 ``` - `SimplifyBranchSame` which transforms `SwitchInt`s to identical basic blocks into a `goto` to the first reachable target. Together, these are meant to simplify the following into just `res`: ```rust match res { Ok(x) => Ok(x), Err(x) => Err(x), } ``` It should be noted however that the desugaring of `?` includes a function call and so the first pass in this PR relies on inlining to substitute that function call for identity on `x`. Inlining requires `mir-opt-level=2` so this might not have any effect in perf-bot but let's find out. r? @oli-obk -- This is WIP, but I'd appreciate feedback. :)
yes. That's what inspired this optimization idea |
[mir-opt] asking `?`s in a more optimized fashion This PR works towards #66234 by providing two optimization passes meant to run in sequence: - `SimplifyArmIdentity` which transforms something like: ```rust _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY ); ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP; discriminant(_LOCAL_0) = VAR_IDX; ``` into: ```rust _LOCAL_0 = move _LOCAL_1 ``` - `SimplifyBranchSame` which transforms `SwitchInt`s to identical basic blocks into a `goto` to the first reachable target. Together, these are meant to simplify the following into just `res`: ```rust match res { Ok(x) => Ok(x), Err(x) => Err(x), } ``` It should be noted however that the desugaring of `?` includes a function call and so the first pass in this PR relies on inlining to substitute that function call for identity on `x`. Inlining requires `mir-opt-level=2` so this might not have any effect in perf-bot but let's find out. r? @oli-obk -- This is WIP, but I'd appreciate feedback. :)
There's still some work here to be done:
|
The
?
operator is not zero cost right now, because the matches generated by it don't get optimized as well as they could.Looking at https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=627df52e7c476667ecf9a9831eecf829
I see
and
Which we could reasonably write a peephole optimization for getting transformed to
each
Then a second optimization could find
switchInt
terminators where all basic blocks are the same and eliminate theswitchInt
by replacing it to a goto to the first basic block being switched to.This will even benefit matches where only one arm is a nop, because that arm will just become a memcopy
The text was updated successfully, but these errors were encountered: