<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/225061>225061</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[LV] Symbolic stride versioning makes the vectorized CoreMark loop unreachable
</td>
</tr>
<tr>
<th>Labels</th>
<td>
backend:RISC-V,
vectorizers,
missed-optimization
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
wangpc-pp
</td>
</tr>
</table>
<pre>
## Description
LoopVectorize reports CoreMark's `matrix_mul_matrix` inner loop as vectorized, but guards the vector path with `N == 1`. Since the loop has exactly `N` iterations, the vector path cannot run for a useful trip count. Every `N > 1` uses the scalar loop.
This reproduces on current trunk: https://godbolt.org/z/44e6WosE9
## Reproducer
```c
void matrix_mul_matrix(unsigned int N, short *C, short *A, short *B) {
unsigned int i, j, k;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
C[i * N + j] = 0;
for (k = 0; k < N; k++)
C[i * N + j] += A[i * N + k] * B[k * N + j];
}
}
}
```
```sh
clang --target=riscv64 -march=rva23u64 -O3 \
-Rpass=loop-vectorize -Rpass-analysis=loop-vectorize \
-S coremark.c -o -
```
Clang reports:
```text
remark: vectorized loop (vectorization width: vscale x 8, interleaved count: 1)
```
## Actual behavior
The optimized IR contains a unit-stride check equivalent to:
```llvm
%ident.check = icmp ne i32 %N, 1
br i1 %ident.check, label %scalar.path, label %vector.path
```
The assembly computes the same condition and merges it into the branch selecting the scalar loop:
```asm
addi t3, a0, -1
snez t3, t3 # N != 1
...
or s3, s3, t3
...
or s5, s5, s3
beqz s5, .Lvector_checks
```
Thus `N > 1` selects the scalar loop, `N == 1` has only one iteration, and `N == 0` returns before the loop. The emitted RVV path never executes with a useful vector trip count.
## Expected behavior
The vectorizer should not specialize this loop for `N == 1`. It should vectorize the general case with gather or strided loads when profitable, or leave the loop scalar.
Disabling unit-stride speculation produces a reachable RISC-V vector loop containing an indexed load and reduction:
```asm
vluxei64.v v26, (a3), v0
...
vredsum.vs v12, v22, v24
```
## Workaround
```sh
clang --target=riscv64 -march=rva23u64 -O3 \
-mllvm -laa-speculate-unit-stride=false \
-S coremark.c -o -
```
## Suspected cause
`LoopAccessInfo::collectStridedAccess` already avoids unit-stride versioning when `Stride >= TripCount`, because `Stride == 1` would imply at most one iteration. The check fails here because the stride and backedge-taken count have different types and extensions:
```text
Stride = %N : i32
MaxBTC = (zext i32 %N to i64) - 1 : i64
```
The current comparison sign-extends `Stride`, producing approximately:
```text
(sext i32 %N to i64) - ((zext i32 %N to i64) - 1)
```
SCEV cannot prove this positive for all i32 values, so LAA adds the useless `%N == 1` predicate. This is a mixed-width variant of the case covered by `llvm/test/Transforms/LoopVectorize/pr34681.ll`.
One possible fix is to rewrite `MaxBTC` under a temporary `Stride == 1` predicate and skip versioning when the result is zero:
```cpp
const SCEV *One = SE->getOne(StrideBase->getType());
const SCEVPredicate *StrideIsOne = SE->getEqualPredicate(StrideBase, One);
const SCEV *VersionedMaxBTC =
SE->rewriteUsingPredicate(MaxBTC, TheLoop, *StrideIsOne);
if (VersionedMaxBTC->isZero())
return;
```
A regression test should use an `i32` symbolic stride with an `i64` IV and a trip count derived from `zext i32 %N to i64`.
----
@BoyaoWang430
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysWF1v4rwS_jXuzSgoOEDpRS8CbaVK--57tN3Tlc7NyjgDeHHsrO2ksL_-aOwQCrSvdKRTIRr8MZ6v55lxhPdqYxDv2XTBpg83og1b6-7fhNk0Mmuam5WtDveMF4wX8IBeOtUEZQ3LS5aXX6xtXlEG69QfBIeNdcHD0jr8S7gd47ce2CyvRXBq_7Nu9c_0yGY5KGPQgba2AeGhOwqpGF_Cqg2waYWrPIQt9pPQiLCFNxW2JPMrsOKBFQ8wZrN8BC_KSIyLo8St8IB7IYM-xMXxwIBOkOqejriUK4UxNoBrDaytAwGtx3WrITjVgLStCSN47NAdjoc_xpNpWVLSS6FFMmiUnPN9qzz5xNmqlejBGpCtc2gCBNeaHStK2IbQeFaUjD8x_rSx1crqMLJuw_jTH8afJhOc_bD-8S6J7OPw7SjU9cOzPH0ky8vOqgquXc7nrYmhrkCZAF_JCX5rXQDGy-XZr_Ls14LxO2C3C5aXAGcyFK37RV87VqR58h3jc0XRgZwVC6DHJXyNj4wv4uckb9jx67Tj12nHr6sdSzZdKFILvgLjtGL6MGztRQ5Cdyehu5PQ3SB0WA-fyOULElBezO3SXAkLNl3sLjad1GC3D_Ep_e-_j5G6CJzfsryUWpgNZFkQboOBFQ9OednNJpDVwsktDXSCFy2N_F0Amy6j_OxbI7xnxQPlXjYgqR_PhBH64NUHCwYBLyCtw1q43UhCZiG71nQZdesRTgl7rn_AfWB5mYRQYp8AnRDJ-Pw4FEEIb6oK27iSkIOwhzllkjIBnUbRYZVgR0vGKVaXzktgKGVohYYVbkWnrDtiD8E2QdVRg-dvIK0JQhlPyDYqZD44VSHILcod4O9WdUJHZNpr47Tu6njeVFVowihtosxQsm7AIKiCA-PTCKoxy8uVAzWG8w00p8UKNY0nthgR9ZyNJx-l8SuDySjhPdYrfQBp66YNR_IRNZKJlYq-FaaCGt0GPahALrVx1coJI7fgUaMMymwueevacuHJcFFVihI6FKSryOk7IzO9wT-niVDA8EeBIUyME0Xn5WhErGhdmvZxg--3vZ_20zgz7efzcoW_4xlpaPQleehndKn_yEetv6DoZO8VS5O4y0ISC4c1-gCWonqsGNFsU50tpyPBYWid8bDCtXWn-jMCChXWKgSs4Nvra6oxBjt0gHuUMXCxlA2Fpi9G7-rNWZY_7huUJO06zweoOSLtVldAlcw3KJXQhPNAhSiiMPLiVfF8DseNJ24gUzZo0AkNUnhM2m5E2KIDilPED4FbVB7etmigcXatglhpJH9ZBxHGp6Lc53xS_EF5sdKUhO_hSEq3OhHEUDcFOBRyS4Lh2_PLMns9OiuK7ZFNooQBZSrc93rFmDmsWhmD-El2d7rdo5pNRl3KzY7PYmrwuSiId_gSunxI0c5h5dt61Pl-9ZjHFbz_N_mUp35YtxPOtqb6f3J_TeQEmRYiOzoPs3cuZcXDWmj_v5F9r_FL6_ukk6L1OKhNXV8pJXr_bNaRL4tSWk0oe0lpkWYJIUI7FNUBBLUl_izYHTqvbAxczB82y9N2gi5l53enmmWsAbPIOSuMepwtPEH3LWawqht9ABGgtj6cozihMpH3WijtYYsOB6mRHpJYypuVkDusNpgFsUOTIAlbSuhKrdeY2rhDQ_lpKsB9QONjc_lZbTypHEsF_NMfFT1VcJaXf4n94vuy3zX_g_swFBsIFtRsQs1RBuN3G2cfJGE0ve8-qXQIp7w1QN1cFpWv_Mmvvb8TAiOwmsbZvapFQH341ELG5_5TBRmf_7MBH9b4l-Xj67E3b5ztejJrrFdBdZh6da2jyE7oFmNz7y18KUsQVX-BaKkE-GhgPPd92jQOKyVFQEoP5UER4dRqj1UWWxTohFPCBLDrKCuSobQdOiLjeB2I_QF_CugD40_fnTB-bV3tGX86uyAx_tS4YjKbj0daE_MmG_82SAZ5RQS3VntSIVhw-OZUiNmekiBeN0yFdDsJWDfWiXQd-QAMg1UxO_1ONVdwI2Mc-lYHOvAPug86H9k0xE3W-AAxFIxHdemcl8eMFY8bDH8bZHyelFgIj_3w90ODMeh39Ild8UnQvwb9GO-R8eyvJD_-boUelp4dQmGOB1-JJomvyVasTvAh8kuCe8f-2yuzeS-89zJfEk98OXYIZ-oNx6k1JfTFMSRc-f-QJwe7iXJTl5A2XuR3CQ43Dj2JAUqgYyUmRhKRE4kHqIs51CurlTxyVOoe0orZhFY8v8Zgi3c9BFToFLXSa2drWvoh_oZMzLIs6zNgki_sQdgfwmwmRQ4sL2-q-6K6K-7EDd6Pb-d3d_P5HS9utvc5z_PbVSX5dJJXq-lsKiayWM3F3e1tzifV-kbd85zP8js-Ho_z-aQYiXE1XeN4IvntbCqnBZvkWAulR4Qkuv3eKO9bvOd8ms_GN7E79vENBeeRl03FijL1AixWXsb5qQ3yw1itvMcq628CfS_H2fThxt3TWdmq3Xg2ybXywZ9ODyro-Ebkyytd9V4uXP8OSbXY4fuXFPG6cXz_kfqT1gzty03r9P3FlV-FbbsaSUsM0hNJ1Kxx9hdKIpToCyKT3h3dPf9vAAAA__8eqGgT">