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

    <tr>
        <th>Summary</th>
        <td>
            Suboptimal code for checking if nth bit is set
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            backend:AArch64,
            missed-optimization
      </td>
    </tr>

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

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

<pre>
    https://godbolt.org/z/h54KPcvKh
```c
bool contains_unchecked(u32 bits, u8 index) {
    return (bits & (1 << index)) != 0;
}

bool contains_checked(u32 bits, u8 index) {
    if (index >= 32) {
        return false;
    }
    return (bits & (1 << index)) != 0;
}
```

For `contains_unchecked`, LLVM generates optimal assembly.
The naive implementation would be
```asm
contains_unchecked:
        lsr     w8, w0, w1
 mov     w8, #0x1
        lsl     w8, w8, w1
        ands    w8, #0x1
        cset    w0, ne
```

But in this case, LLVM is smart enough to rewrite `(bits & (1 << index)) != 0` to `(bits >> index) != 0` and so save 2 instructions:
```asm
contains_unchecked:
        lsr w8, w0, w1
        and     w0, w8, #0x1
 ret
```

However, LLVM fails to make the same optimization when bounds checking is added to avoid UB:
```asm
contains_checked:
 mov     w8, #1
        and     w9, w1, #0xff
        lsl     w8, w8, w1
        tst     w8, w0
        mov     w8, #32
        ccmp w9, w8, #2, ne
        cset    w0, lo
        ret
```

I believe the optimal assembly would be:
```asm
        lsr     w8, w0, w1
        and     w0, w8, #0x1
        and     w9, w1, #0xff
 cmp     w9, #32
        csel    w0, w0, wzr, ls
        ret
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVl2P6jYQ_TXOy2hRsENIHvLALhe12lupUj9eKyceiLuOjTwO3Lu_vnL4ygJ3u1sVIRKYGc85Z45jJJHeWMSKzR7ZbJnIPrTOV88dyhdtk9qp71UbwpaYWDC-Yny1cap2Jkyc3zC-emV81c6y51-b3XPL0iVLFyxPD-_m8L12zkDjbJDa0l-9bVpsXlAxXvSCQ60DMf4EfQHaKvzGeAls_ngoBQDwGHpvgfEipgLjebyfAhNPTDydi4Y6PmViCSkTx3o2Xx5v7iD5JA69jn2HGDDxJTYS_CZrhHgtDeEZSgyc4fx_vE5aj2munIco_63keRopfv365y-wQYteBiRw26A7aUASYVeb75PDKr-3CFbqHYLutgY7tEEG7SzsXW8U1HiFQFJ3-OVOX7F4q5AhP1z3RcSzH1Dtp8eczu1GQcZF-m16XW7G5cWb8uNLWkXvr9IQhiFjaG-v-YwVfewDaAuh1QSNJDyrqAmokz4AWtdvWggOPO69DgiD2J-YbZ7G6nFVNNmXkRtHmdIqIAckdwgctKXg-yZOh85a_-fB3B3KRVW4aHZHW4_hHR1_cnvcoT_Lt5baUKTdyReE0CKQ7PDgSP16tFuLFmrXx3kOsLXdRN2lUqhirdw5reCPx48wv-F9Y7YfES6PcpwIr9ef92Sg8Nb2b6I3UAS_MmzTbU9ATjl87N37zjbu5vH0zoh-hhqNxt1hHNfPhsvm_7HYH9rkH_XTh8cQtblk3FOP0IxaHT5fBy8a-jeFElUJVYpSJlhN51zwTJR5lrTVdJZikanpel5KWahSFlhOy7mSeSFmPM0TXfGUZ2mRlpzPeJZN5s18Ni-FymUmmgwFy1LspDYTY3ZdPFUTTdRjNU15XmaJkTUaGo5nzmvZvKCN9l0sfNPmGePRAIzzThOhehjvnBibLRNfxYUf6n5DLEuNpkCXVkEHg9VvfX0adOMUwtr50VZbgw1tPB-Hpx2GpPfm-j-BDm1fTxrXMb6Kix8vD1vv_sYmML4aSBHjqyOvXcX_CQAA__9qD09V">