[AArch64][SVE] Missed vectorization opportunity for early-exit loop with store and multiple exits compared to GCC
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
**Description:**
Clang fails to auto-vectorize a nested loop with early exit (`break`), a conditional store, and strided memory access on AArch64 with SVE enabled, while GCC successfully vectorizes the same loop under identical compilation flags.
The inner loop contains a conditional store (`out[idx] = ...`) guarded by `a[idx] != 0`, followed by an early exit when `a[idx] != -1`. This creates two distinct control flow divergences within the same loop. Clang 21.1.1 reports that it cannot vectorize loops with more than one early exit. Clang trunk, while showing improved diagnostic precision, reports that it cannot handle a store within an early-exit loop without a supported condition load. In contrast, GCC 16.0.1 successfully handles this pattern using loop versioning and generates vectorized code.
**Test case:**
```c
#include
#include
int foo(
const int * __restrict__ a,
int * __restrict__ out,
int n,
int m) {
for (int i = n - 1; i >= 0; i -= 2)
{
for (int j = m - 1; j >= 0; j -= 1)
{
int idx = i * m + j;
if ((a[idx] != 0)) {
out[idx] = (((int)a[(idx + 27)]));
}
if ((a[idx] != -1)) {
break;
}
}
}
return (int)0;
}
```
**clang version (Clang 21.1.1):**
```
clang version 21.1.1
Target: unknown
Thread model: posix
Build config: +unoptimized, +assertions
```
**Clang options:**
```
-S -O3 -ftree-vectorize -ftree-slp-vectorize --target=aarch64-linux-gnu -march=armv9-a+sve -Rpass=.*vectorize.* -Rpass-missed=.*vectorize.* -Rpass-analysis=.*vectorize.*
```
**The result of Clang 21.1.1:**
```
test.c:11:9: remark: loop not vectorized: Cannot vectorize early exit loop with more than one early exit [-Rpass-analysis=loop-vectorize]
11 | for (int j = m - 1; j >= 0; j -= 1)
| ^
test.c:11:9: remark: loop not vectorized [-Rpass-missed=loop-vectorize]
```
Also reproducible on Godbolt (https://godbolt.org/z/EqbGbj187).
**clang version (Clang trunk):**
```
clang version 23.0.0git (https://github.com/llvm/llvm-project.git 793bdd8597894c6efafc98ef8ddfbf6292a8024c)
```
**The result of Clang trunk:**
```
test.c:11:9: remark: loop not vectorized: Early exit loop with store but no supported condition load [-Rpass-analysis=loop-vectorize]
11 | for (int j = m - 1; j >= 0; j -= 1)
| ^
test.c:11:9: remark: loop not vectorized [-Rpass-missed=loop-vectorize]
```
Also reproducible on Godbolt (https://godbolt.org/z/YvW4vE77W).
**However, GCC vectorizes it.** GCC version 16.0.1.
**gcc version:**
```
aarch64-linux-gnu-gcc (GCC) 16.0.1 20260419 (experimental)
Copyright (C) 2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```
**GCC options:**
```
-S -march=armv9-a+sve -ftree-vectorize -O3 -fopt-info-vec-all
```
**The result of GCC:**
```
test.c:9:27: missed: couldn't vectorize loop
test.c:9:27: missed: not vectorized: unsupported outerloop form.
test.c:11:31: optimized: loop vectorized using 16 byte vectors and unroll factor 4
test.c:11:31: optimized: loop versioned for vectorization to enhance alignment
test.c:4:5: note: vectorized 1 loops in function.
test.c:13:17: note: ***** Analysis failed with vector mode VNx4SI
test.c:13:17: note: ***** The result for vector mode VNx16QI would be the same
test.c:13:17: note: ***** Re-trying analysis with vector mode VNx8QI
test.c:13:17: note: ***** Analysis failed with vector mode VNx8QI
test.c:13:17: note: ***** Re-trying analysis with vector mode VNx4QI
test.c:13:17: note: ***** Analysis failed with vector mode VNx4QI
test.c:13:17: note: ***** Re-trying analysis with vector mode VNx2QI
test.c:13:17: note: ***** Analysis failed with vector mode VNx2QI
test.c:13:17: note: ***** Re-trying analysis with vector mode V16QI
test.c:4:5: note: ***** Analysis failed with vector mode V16QI
test.c:4:5: note: ***** Re-trying analysis with vector mode V8QI
test.c:4:5: note: ***** Analysis failed with vector mode V8QI
test.c:4:5: note: ***** The result for vector mode V4HI would be the same
test.c:4:5: note: ***** Re-trying analysis with vector mode V2SI
test.c:4:5: note: ***** Analysis failed with vector mode V2SI
```
Also reproducible on Godbolt: https://godbolt.org/z/4b5hGvodr.
**Additional Notes:**
This case reveals two distinct limitations in Clang's early-exit vectorization:
1. **Clang 21.1.1**: `Cannot vectorize early exit loop with more than one early exit` — Clang 21.1.1 treats the conditional store (`if (a[idx] != 0)`) as a second "early exit" path, even though the store itself does not exit the loop. This suggests the analysis conflates control flow divergence with early exits.
2. **Clang trunk**: `Early exit loop with store but no supported condition load` — The trunk diagnostic has evolved to be more precise. It now correctly identifies the store as the problem (not a second early exit), but reports that the store in an early-exit loop requires a "supported condition load" pattern that is not yet implemented. This likely refers to the need for a predicated store mechanism that can safely handle the interaction between the store condition (`a[idx] != 0`), the early exit condition (`a[idx] != -1`), and the strided access pattern (`idx + 27`).
3. **GCC 16.0.1** successfully versions the loop, creating a vectorized path that handles both the conditional store and the early exit, with a scalar fallback for when the break condition is triggered.
Contributor guide
Research direction
Start by compiling the supplied test.c with Clang trunk and AArch64 SVE options, then inspect the loop-vectorizer analysis and missed-vectorization remarks. Compare the generated result with GCC's vectorized loop and use the reported conditional store, early exit, and strided access as the scope. Done means Clang can vectorize this case or the repository has a focused regression test documenting the supported behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100