avoid overflow cases to help eliminate bounds checks - #16
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? |
droundy
commented
Feb 16, 2019
I have not experimented with this at all, and have no idea. |
oconnor663
commented
Feb 16, 2019
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 |
oconnor663
commented
Mar 28, 2019
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):