-
Notifications
You must be signed in to change notification settings - Fork 13k
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
opt-level=z
fails to remove bounds checks/panics even if every other opt-level succeeds
#115463
Comments
I see two problems here:
|
Is there a reason to assume Edit: Ah, there's a godbolt link. Note that this kind of indexing is extremely common in certain code (including commonly used functions like hash implementations), and isn't always as simple as the example (which is just first/last). It would be better if we could just do better in opt-level=z. Even opt-level=1 gets this right. |
If there's an Have you perchance looked at |
Yes -Os is fine (I mentioned as much above). The only two opt-levels with issues here are 0 (which is expected) and z (which is not). Note that in practice using if-let is viable for this version of the function, but it usually is not viable for this pattern. |
Tune the inlinability of `unwrap` Fixes rust-lang#115463 cc `@thomcc` This tweaks `unwrap` on `Option` & `Result` to be two parts: - `#[inline(always)]` for checking the discriminant - `#[cold]` for actually panicking The idea here is that checking the discriminant on a `Result` or `Option` should always be trivial enough to be worth inlining, even in `opt-level=z`, especially compared to passing it to a function. As seen in the issue and codegen test, this will hopefully help particularly for things like `.try_into().unwrap()`s that are actually infallible, but in a way that's only visible with the inlining.
Tune the inlinability of `unwrap` Fixes rust-lang#115463 cc `@thomcc` This tweaks `unwrap` on `Option` & `Result` to be two parts: - `#[inline(always)]` for checking the discriminant - `#[cold]` for actually panicking The idea here is that checking the discriminant on a `Result` or `Option` should always be trivial enough to be worth inlining, even in `opt-level=z`, especially compared to passing it to a function. As seen in the issue and codegen test, this will hopefully help particularly for things like `.try_into().unwrap()`s that are actually infallible, but in a way that's only visible with the inlining.
Tune the inlinability of `unwrap` Fixes rust-lang#115463 cc `@thomcc` This tweaks `unwrap` on ~~`Option` &~~ `Result` to be two parts: - `#[inline(always)]` for checking the discriminant - `#[cold]` for actually panicking The idea here is that checking the discriminant on a `Result` ~~or `Option`~~ should always be trivial enough to be worth inlining, even in `opt-level=z`, especially compared to passing it to a function. As seen in the issue and codegen test, this will hopefully help particularly for things like `.try_into().unwrap()`s that are actually infallible, but in a way that's only visible with the inlining. EDIT: I've restricted this to `Result` to avoid combining effects
…kingjubilee Tune the inlinability of `unwrap` Fixes rust-lang#115463 cc `@thomcc` This tweaks `unwrap` on ~~`Option` &~~ `Result` to be two parts: - `#[inline(always)]` for checking the discriminant - `#[cold]` for actually panicking The idea here is that checking the discriminant on a `Result` ~~or `Option`~~ should always be trivial enough to be worth inlining, even in `opt-level=z`, especially compared to passing it to a function. As seen in the issue and codegen test, this will hopefully help particularly for things like `.try_into().unwrap()`s that are actually infallible, but in a way that's only visible with the inlining. EDIT: I've restricted this to `Result` to avoid combining effects
…kingjubilee Tune the inlinability of `unwrap` Fixes rust-lang#115463 cc `@thomcc` This tweaks `unwrap` on ~~`Option` &~~ `Result` to be two parts: - `#[inline(always)]` for checking the discriminant - `#[cold]` for actually panicking The idea here is that checking the discriminant on a `Result` ~~or `Option`~~ should always be trivial enough to be worth inlining, even in `opt-level=z`, especially compared to passing it to a function. As seen in the issue and codegen test, this will hopefully help particularly for things like `.try_into().unwrap()`s that are actually infallible, but in a way that's only visible with the inlining. EDIT: I've restricted this to `Result` to avoid combining effects
|
If compiling with
-Copt-level=z
we fail to remove bounds checks and panicking branches in code like this (godbolt https://godbolt.org/z/YsoMszxPe):Unfortunately, while
-Copt-levels=[123s]
all manage to remove the panic branches,-Copt-level=z
does not, leading to a lot more code and significantly worse performance.Note that we do manage to remove it in cases where the function does less stuff -- it's removed entirely in simple examples that do nothing other than load the value from a slice. However, in real code, (perhaps after a layer of inlining) you tend to have a couple of these in a function, and this issue seems to crop up again1.
Given that this pattern is more or less the recommended "safe" way to read a u32 out of a &[u8], this seems unfortunate to me.
Footnotes
Although not 100% reliably -- having trouble reproducing on godbolt, but it seems like it's happening in real-world code. ↩
The text was updated successfully, but these errors were encountered: