llvm / llvm/llvm-project

Clang 21/22 fails to vectorize masked positive-sum loop on ARM SVE.

Open
#196,703 1 comment 0 reactions 1 assignee Claimed by @mkovacevic99 View on GitHub
missed-optimization SVE vectorizers
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

# Summary

Clang 21/22 fails to vectorize masked positive-sum loop on ARM SVE.

# Details

We kindly observe that Clang 21/22 cannot vectorize this simple conditional reduction loop (sum if positive), whereas GCC 15/16 vectorizes it efficiently with SVE.

The reported reason ("value that could not be identified as reduction is used outside the loop") seems to be a missed pattern, as the reduction variable `sum` is only used after the loop.
We would greatly appreciate it if the LLVM team could consider improving the reduction recognition for such conditional idioms.

Thank you for your understanding and continued excellent work.

Test case:

```c
#include

void foo(const float * __restrict__ a, float * __restrict__ out)
{
float x;
float sum = 0.0f;

for (int i = 0; i < 102400; i += 1) {
x = a[i];

if ((x) > (0.0f)) {
sum += x;
}
}

out[0] = sum;
}
```

Clang Compilation Options

`-march=armv9-a+sve -S -O3 -Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize`

GCC Compilation Options

`-O3 -S -march=armv9-a+sve -ftree-vectorize -fopt-info-vec-all`

## Clang Behavior

Clang 21.1.0 and 22.1.0 do not vectorize the loop.

Clang 21.1.0 log

```
:8:5: remark: loop not vectorized: value that could not be identified as reduction is used outside the loop [-Rpass-analysis=loop-vectorize]
8 | for (int i = 0; i < 102400; i += 1) {
| ^
:8:5: remark: loop not vectorized [-Rpass-missed=loop-vectorize]
Compiler returned: 0
```

Clang 22.1.0 log

```
:8:5: remark: loop not vectorized: value that could not be identified as reduction is used outside the loop [-Rpass-analysis=loop-vectorize]
8 | for (int i = 0; i < 102400; i += 1) {
| ^
:8:5: remark: loop not vectorized [-Rpass-missed=loop-vectorize]
Compiler returned: 0
```

Clang 22.1.0 output

```asm
foo(float const*, float*):
movi d0, #0000000000000000
mov x8, xzr
.LBB0_1:
ldr s1, [x0, x8]
add x8, x8, #4
fadd s2, s0, s1
fcmp s1, #0.0
fcsel s0, s2, s0, gt
cmp x8, #100, lsl #12
b.ne .LBB0_1
str s0, [x1]
ret
```

## GCC Behavior

GCC 15/16 successfully vectorizes the same loop.

```
:8:23: optimized: loop vectorized using variable length vectors
:8:23: optimized: epilogue loop vectorized using variable length vectors
:3:6: note: vectorized 1 loops in function.
:17:1: note: ***** Analysis failed with vector mode VNx4SF
:17:1: note: ***** Skipping vector mode VNx16QI, which would repeat the analysis for VNx4SF
Compiler returned: 0
```

# Potential Cause Analysis

1. Masked Reduction Not Recognized
Clang indicates that the value could not be identified as a reduction. The if (x > 0.0f) conditional prevents the loop vectorizer from recognizing sum += x as a masked reduction, even though ARM SVE supports predicated operations.

2. Scalar Dependence Misinterpretation
`sum` is used outside the loop. The conditional accumulation may make Clang conservatively treat `sum` as a scalar dependency, preventing vectorization.

3. GCC Vectorization Shows Feasibility
The GCC output confirms that SVE masked vector reduction is feasible, suggesting Clang could improve loop vectorizer analysis for this case.

# Expected Behavior

Clang should recognize `sum += x` under `if (x > 0.0f)` as a masked floating-point reduction.

Generate SVE vector code using predicated operations, similar to GCC.

# Notes

This is a small, reproducible test case.

The loop is a classic candidate for vectorization on SVE due to independent iterations and predictable memory access.

Supporting masked reductions would allow Clang to generate highly efficient code for this pattern.

If you could provide some guidance on a possible fix, I would be happy to give it a try!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.