<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/79665>79665</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            RISCV __riscv_vsetvl() and __riscv_vsetvlmax() intrinsics fail to inform optimiser about return constraints
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          sh1boot
      </td>
    </tr>
</table>

<pre>
    By wrapping the intrinsic `__riscv_vsetvlmax_u8m1()` in a function which exposes some additional details about the behaviour of the operations, like so:
```C
 __attribute__((const)) inline size_t get_vlmax_u8m1() {
    size_t vlmax = __riscv_vsetvlmax_e8m1();

#if defined __riscv_v_fixed_vlen
 constexpr size_t fixed_vl = __riscv_v_fixed_vlen / 8;
    if (vlmax != fixed_vl) __builtin_unreachable();
#else
    constexpr size_t min_vl = __riscv_v_min_vlen / 8;
    if (vlmax < min_vl) __builtin_unreachable();
#endif

    return vlmax;
}

 __attribute__((const)) inline size_t set_vl_u8m1(size_t avl) {
    size_t vl = __riscv_vsetvl_e8m1(avl);

#if defined __riscv_v_fixed_vlen
 constexpr size_t fixed_vl = __riscv_v_fixed_vlen / 8;
    if (avl <= fixed_vl && vl != avl) __builtin_unreachable();
    if (avl >= fixed_vl * 2 && vl != fixed_vl) __builtin_unreachable();
#else
    constexpr size_t min_vl = __riscv_v_min_vlen / 8;
    if (avl <= min_vl && vl != avl) __builtin_unreachable();
#endif

    return vl;
}
```

The optimiser can then use this knowledge to elide more dead code.  For example:

```C
inline void generic(void* data, size_t len) {
    uint8_t* ptr = reinterpret_cast<uint8_t*>(data);
 size_t vl = get_vlmax_u8m1();
    vuint8m1_t zero = __riscv_vmv_v_x_u8m1(0, vl);
    while (len > vl) {
 __riscv_vse8(ptr, zero, vl);
        ptr += vl;
        len -= vl;
 }
    __riscv_vse8(ptr, zero, len);
}

inline void generic2(void* data, size_t len) {
    uint8_t* ptr = reinterpret_cast<uint8_t*>(data);
    size_t vl = set_vl_u8m1(len);
 while (len > 0) {
        vuint8m1_t zero = __riscv_vmv_v_x_u8m1(0, vl);
        __riscv_vse8(ptr, zero, vl);
        ptr += vl;
 len -= vl;
        vl = set_vl_u8m1(len);
    }
}

void u64_wrapper(uint64_t& data) {
    generic(&data, sizeof(data));
}

void u64_wrapper2(uint64_t& data) {
 generic2(&data, sizeof(data));
}

void generic_wrapper(void* data, size_t len) {
    generic(data, len);
}

void generic_wrapper2(void* data, size_t len) {
    generic2(data, len);
}
```

The hints allow the `u64_wrapper()` functions to emit trivial, straight-through code with no loops.  Removing the hints makes these functions perform unnecessary tests and loops.

I'm not 100% sure I defined the hints correctly, but something like that.  Knowledge of the target might help further.

Perhaps these hints could be embedded in the intrinsics themselves?

https://godbolt.org/z/P4z9a5jjT
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMV01v2zgQ_TX0ZZBApmzFPvjQJDVQ7KXoFnsVKHFksaVIgRzZSX79grQUy7LbNOgC2yBIYGs-3sx7HA2F92pnEDdsec-WjzPRUW3dxtfzwlqaFVY-b-6f4eBE2yqzA6oRlCGnjFclsCzJc6d8uc_3HmmvG_GUd6tmzviK8TXLElAGBFSdKUlZA4dalTXgU2s9evC2QRBSqvBMaJBIQmkPorAdxVQF1mKvbOfAVvEL26ITwdwz_gBafUfwlqUfWPLIkg8sS46_D8fPkOeCyKmiI8zzCGpVWuMpgONrUEYrg-DVC-YEO6R8WgKwu_s-FsBgGI2ApY9wWT2eqk97z_4vT1UFEitlUJ4c80o9ocz3Gk2fJwLEp9YN6QaL84wjR2B8C6vXfAGpqoDxVQ-Uz4PnYB-qyvOiU5qUyTvjUJS1KDROYfMUtcdTzAtgjTKXsI5fvg0qfej934PHSFWNmxqiOqTOmSMpJ-O7xzO7dwnBRyEMKui_FEek1_VwRQyDEo5-f4AYRHR6GEsBGM8Yz2IBR5GIX-djGvnjJPIH4Jfx_xQRjpoxBPiNVrwpzSu6HEbV2OdrnHCkGuXRQSlMmHkGOo9AtfLw3diDRrlDIAuolURorEOQKCSUVuItwNY6wCfRtBpPc_HqdOxFv7dKwg4NOlWG42mVDORJQSLM2L7NQZJT-XfK0CqnYN2SixQ4VIbQtQ4pL4Unlj6crIJG-OoYeKSj81N0bQqfEbiPAZt5TvCCzp4z3wT2X12TUMD5-QsRDrXSGFQQFZJ-hOnRHp3kMClaciFQyHY9YPiJHeD3Ac2I7-FpyHQzffYqhmDx85zH9v9ovF1hkv8vVF7MxPNROqnikojkAth_w_jbDX4XqVfZHMD-SuEAJ_InXEYSu2yRx50LHeOrUH62CH3Pei4nTTqdXsazMdu2GrH0Y_1Mc_I3k45U9hsp-yijUt8h2VPRg_HPD8m1jO88JaOq38z5o_leK0MehNb2EDdaliXnbPeL87Az-zjrG0VATu2V0BEjOaF2Nd1Q7Wy3q-Pwh4OiGowFbW3rbwG-YGP3w9Z-zNuI7-jDZ4-jDC26yroGOmOwRO-FewZCH3Aa2Ycb1_GJ8bsGjCWYJwnjS_CdQ_j0utCc8pXWOSxJPwfURUdx56c6gIrLO9WCbgH-en2x9Xs-CbfD8HLf1QQ16haqzlGN7gzHZ3S1aId6hoydllAgYFOglCjDFeTs2hLtG496j56l23HAmqj14bXJt4xvd1YWVtOtdTvGty-Mbz8vXtZi-e3b15ncpHKdrsUMN_O7JEvn8_lqOas3qzVfIl-u06Tky3V2l8hyOS9wna6qNMFiPVMbnvBFMucZT-frxeK2WqQLsU7nMkmzNMsKtkiwEUrfar1vQu6Z8r7Dzd06y5YzLQrUPl7XODd4gPiQcR5ub24TfG6KbufZItHKkz9FIUUaN18-_f3wz2RV7a86geuLC03_bNS8SigdNKlM1MxpXzle2_qdJ-5pTgRKZp3Tm0lnFdVdcVvahvFtQNj_u2md_YYlMb6NdXnGt7HufwMAAP__R-51ig">