<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">