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

    <tr>
        <th>Summary</th>
        <td>
            [X86] Unneded stack moves when converting bit vectors to arrays of i8
        </td>
    </tr>

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

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

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

<pre>
    Rust's `portable_simd` project represents vector masks internally as an array of i8 when compiled for avx512 targets. This is done in order to support potentially arbitrary number of vector lanes in the api, but seems to lead to bad codegen when converting masks with more than 8 lanes.

I was able to reduce the problem to the following llvm code ([compiler explorer](https://llvm.godbolt.org/z/9sYGeG7s4))

```llvm
define [2 x i8] @is_nan(<16 x float> %data) {
  %mask = fcmp uno <16 x float> %data, zeroinitializer
  %i = bitcast <16 x i1> %mask to i16

  %tmp = alloca [2 x i8], align 1
  store i16 %i, ptr %tmp, align 1
  %r = load [2 x i8], ptr %tmp, align 1
  
  ret [2 x i8] %r
}
```

which gets optimized to

```llvm
define [2 x i8] @is_nan(<16 x float> %data) local_unnamed_addr #0 {
  %mask = fcmp uno <16 x float> %data, zeroinitializer
  %bc1 = bitcast <16 x i1> %mask to <2 x i8>
  %tmp.sroa.0.0.extract.trunc = extractelement <2 x i8> %bc1, i64 0
  %tmp.sroa.2.0.extract.trunc = extractelement <2 x i8> %bc1, i64 1
  %r.fca.0.insert = insertvalue [2 x i8] poison, i8 %tmp.sroa.0.0.extract.trunc, 0
  %r.fca.1.insert = insertvalue [2 x i8] %r.fca.0.insert, i8 %tmp.sroa.2.0.extract.trunc, 1
  ret [2 x i8] %r.fca.1.insert
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn }
```

And when compiled for `skylake-avx512` results in the following assembly

```asm
is_nan:                                 # @is_nan
        vxorps  xmm1, xmm1, xmm1
        vcmpunordps     k0, zmm0, zmm1
        kmovw   word ptr [rsp - 2], k0
        kmovd   eax, k0
        movzx   edx, byte ptr [rsp - 1]
        vzeroupper
        ret
```

I'm not fully sure about the calling conventions for returning a 2-element array, but returning the value using two registers should be possible without moving to the stack first. These moves through the stack also stay when the small sample function is used in a bigger context.

This was noticed while investigating [weird codegen in Rust's portable_simd project for avx512](https://github.com/rust-lang/portable-simd/issues/312)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1Vstu2zgU_Rp5cxFDkuXXwou2aYtuBzPAzCqgJEpmTZECSfnRr59zKSWxkzRTYFD5QUkkz33y3lPa-rL7Y_AhydeeklXaWxdEqeWDV12NZ-qd_S6rQE72Tnppgqcjnq2jTviDJ2WCdEZofSHhSRgSzokL2YbUhk57aaiyXa-0rKnBJnE8L7OcgnCtDH5Of-4VMDzV1khgkXW1dBQs-aFnXai3AULVKMCVKjjhLmSGrsQ6SJmU0cJIVobCXpLoVZJ_onII5KXsPONpKWoeSwyVrWULzSb1zFG6oEw7WXRSYU-ddRJYsGczYs-T9D5JP4z_3-jExsJPDOlkPVQySoa38LLjt_zYWK3tiaG1PnZRLiX5Jll-nJziSJ57DVkuWd5jZh9C75PFhyT_gi9vmre2Lq0Oc-tavPqB39b_81V-Xfsiybf8vVIMERu_vHV8VctGwbeQmdMZQYEgSopU-QcjDCuz-JStMNNoK0Ky-AwFl7UIAsiUrD-OIMRv2T2ULO6pqbqeBmPp53s_0Q_prDKKQ6dwf4WjIghCWQkfnjBUNgFEMXCgylbXpsWtAYJ5M9LBVuLGKJYJUa2h7HGDDxxF4ESpvKAPboJ5YzkmXESHNfUr7Pe3TqOT4YWngTlZsb5_EaNr6057Ve2JzwTZPqgOLuN0_Y2xZQfqh8EY0cn6QdQ1m7dIf1PMyyr7tahjYrJl8fk28HPvrJin-MgzqkAV5sENpoqw0xuJs4dqcQMySWf11Kqg9C3Q_H-C3qTQvKlYTWU8ykoEGm-PQg8vYtVb5a2JKJv3reQ16Ssp2S9JeaXUGwJfeYDXZO-m9Y0GL3M8_osQnEIVRmUeUwtaIr2oQ8NBpWzRUDwZ2zgpMThZDc7znb8gAsYOBqWzhnBRG24PJ6U1NBmcofcP0wfset16sMgfLloc5N3Yhbi9QYVBh6fO8VywhfeyK_XlzRMo_HQAp5O2gI_-44IDro7m5NfxOp6t6z3RuetiRt2MtytxCHEGXc3LcR3SeOq67nF8sf7Q2eMJ4wlbxgK2_Oh8T3eUT1XtkL7eUWOU4vzWNGZ_nHm6jtPlJchb3Ixxb3XmooBm_lwOxguRfCeE30BIOuRAoGbg1u8HVHJRWrR0jhNKl-YoxeYNemCNjzEe0yPGj_K7x5MbKckjI3hewkDjcRl8fD5xL2-VB6Px5Pd20DWVMNB6r7jXMzNgDeCFuH5s8j6I6kCNcj4wnwFJ4gXI-bCH4e3-apHQ3vLtZUzPONHBFPKi6yGgwcFjY5gRDR55i7QUqJltC6YAWwOO6A0RifSJuQg8pSrJaY98xzbID6oVkdYgOCep3DPvAeoT57shfE9s75mqvcVLWvhhKOc4XXhwQLoDRWJ28gh2F9lj_kV5P0iPmwWA8u1M7rLValUs18V6O6t3i3q72IpZUEHLHbT8e7Pi4vKXMbKGLaPPRl--pGroIxP1i-wuRtiPrHM2OL17R-HYPsfhbrL3WtXlZlmsZvudTNPFZr3AryqaVV2kpVyXYiPLTZ5VRZXPtCil9qx3kudGnihC4B42zNQuT_M8499qmWXbuaiblazSImuKYtsUC9QC2Qml55HkgdzN3C6qVA6tx6RGGvrnSZQjEA4Z3cT4YkAqut13_PnQCWNmUfouav8vnQqkpg">