]> git.ipfire.org Git - thirdparty/gcc.git/commit
middle-end: Enable masked load with non-constant offset
authorKarl Meakin <karl.meakin@arm.com>
Tue, 15 Jul 2025 14:49:58 +0000 (14:49 +0000)
committerAlfie Richards <alfie.richards@arm.com>
Tue, 22 Jul 2025 15:01:12 +0000 (15:01 +0000)
commit0d52a736a3856871761c89fefa59c2ff39f3a5f8
treefa20ea296499b426faa92b634ba360952a5d957a
parent626d67f0fb9696434152de97e80b2c0a7e85f15a
middle-end: Enable masked load with non-constant offset

The function `vect_check_gather_scatter` requires the `base` of the load
to be loop-invariant and the `off`set to be not loop-invariant. When faced
with a scenario where `base` is not loop-invariant, instead of giving up
immediately we can try swapping the `base` and `off`, if `off` is
actually loop-invariant.

Previously, it would only swap if `off` was the constant zero (and so
trivially loop-invariant). This is too conservative: we can still
perform the swap if `off` is a more complex but still loop-invariant
expression, such as a variable defined outside of the loop.

This allows loops like the function below to be vectorised, if the
target has masked loads and sufficiently large vector registers (eg
`-march=armv8-a+sve -msve-vector-bits=128`):

```c
typedef struct Array {
    int elems[3];
} Array;

int loop(Array **pp, int len, int idx) {
    int nRet = 0;

    for (int i = 0; i < len; i++) {
        Array *p = pp[i];
        if (p) {
            nRet += p->elems[idx];
        }
    }

    return nRet;
}
```

gcc/ChangeLog:
* tree-vect-data-refs.cc (vect_check_gather_scatter): Swap
`base` and `off` in more scenarios. Also assert at the end of
the function that `base` and `off` are loop-invariant and not
loop-invariant respectively.

gcc/testsuite/ChangeLog:
* gcc.target/aarch64/sve/mask_load_2.c: Update tests.
gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c
gcc/tree-vect-data-refs.cc