avoid overflow cases to help eliminate bounds checks#16
avoid overflow cases to help eliminate bounds checks#16oconnor663 wants to merge 1 commit intodroundy:masterfrom
Conversation
Currently `array_ref!` takes a slice this way:
let slice = & $arr[offset..offset + $len];
If the length of `slice` is already known, the compiler should be able
to skip bounds checks there. However, because of the possibility that
`offset + $len` might overflow, the compiler sometimes has to be
conservative. Switching to slightly different slicing arithmetic avoids
this problem:
let slice = & $arr[offset..][..$len];
Here's an example of the second version successfully eliding bounds
checks, where the first version does not (https://godbolt.org/z/Je4lRl):
fn get_array(input: &[u8], offset: usize) -> Option<&[u8; SIZE]> {
if input.len() >= offset && input.len() - offset >= SIZE {
Some(array_ref!(input, offset, SIZE))
} else {
None
}
}
|
I think this might be a win in some practical cases. However, I've found at least one contrived case where it appears to be a loss. If we tweak the example above to use a constant-size input array, and then simplify the if-condition: In this case, it's the new approach that fails to elide bounds checks. I have no idea why. https://godbolt.org/z/dMqF2o Have you experimented with this stuff before? Do you have any intuition about why this second example is failing to optimize? |
|
I have not experimented with this at all, and have no idea. |
|
I've asked for advice on the subreddit, fingers crossed that someone there knows more: https://www.reddit.com/r/rust/comments/arcavd/why_does_rustc_eliminate_bounds_checks_in_one |
|
Holy crap apparently they're working on a fix for this :) |
Currently
array_ref!takes a slice this way:If the length of
sliceis already known, the compiler should be ableto skip bounds checks there. However, because of the possibility that
offset + $lenmight overflow, the compiler sometimes has to beconservative. Switching to slightly different slicing arithmetic avoids
this problem:
Here's an example of the second version successfully eliding bounds
checks, where the first version does not (https://godbolt.org/z/Je4lRl):