Skip to content

Autovectorization fails if a field follows an array #121276

Open
@EsotericPyramid

Description

@EsotericPyramid

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-autovectorizationArea: Autovectorization, which can impact perf or code sizeC-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions