I have a task that requires reading and writing to the same slice at different locations, and I can't convince Rust/LLVM to eliminate bounds checks in this case.
pub fn why_u_no_optimze(inout: &mut [u8], len: usize, offset: usize) {
if inout.len() < len || inout.len() < offset || offset >= len || len >= u32::MAX as usize || offset > 8 {
return;
}
for i in offset..len {
inout[i] = inout[i-offset] + 1;
//inout[i] = unsafe { *inout.get_unchecked(i-offset) } + 1;
}
}
Using unsafe of course can work around the problem. But it's weird how stubborn LLVM is here.
changing [i-offset] to [i] eliminates bounds checks. But as far as I can tell, any arithmetic on the offset, even checked or saturating, ruins it.
And sadly due to aliasing, I can't use separate slices (chunking them or copying generates worse code than I'd like).
What's going on here? Is there safe code that optimizes better?
While trying to eliminate bound checks in a similar case I found that signed integers, i.e. isize instead of usize, have better correlation propagation. I still have it on my to do list to find the correct place to file an issue. Here a minimal example: Compiler Explorer