Open
Description
The following code fails to be autovectorized on opt-level=3 despite it being safe to do so:
struct ArrayIter{arr: [i32; 10000],start: usize}
pub fn main() {
let mut array_iter = ArrayIter{arr: [10; 10000],start: 0};
let arr_ref = &mut array_iter.arr;
let start_ref = &mut array_iter.start;
while *start_ref < 10000 {
let index = *start_ref;
*start_ref += 1;
arr_ref[index] = 100 * arr_ref[index]
}
assert_eq!(array_iter.arr,[1000; 10000]);
}
Looking at LLVM pass remarks, it states that
remark: test.rs:7:11: loop not vectorized: value that could not be identified as reduction is used outside the loop
remark: test.rs:7:11: loop not vectorized: could not determine number of loop iterations
neither of which make sense as start_ref
should be a reduction and the number of loop iterations can be determined.
As such, I'm guessing that LLVM for some reason thinks that the writes or reads done with array can somehow interact with start_ref
in some way when that is clearly impossible.
Additionally, if you manually specify the order of ArrayIter
's fields using Repr(C)
, it does get autovectorized if start
comes before arr
as seen here. Furthermore, it will also be autovectorized if you add some padding as seen here