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

    <tr>
        <th>Summary</th>
        <td>
            Optimizing (x & (-1 << y)) to ((x >> y) << y) or vice versa
        </td>
    </tr>

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

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

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

<pre>
    ### Test code

```c
#include <stdint.h>

unsigned int func1(unsigned int x, unsigned char count)
{
  return (x >> count) << count;
}

unsigned int func2(unsigned int x, unsigned char count)
{
  return x & (~0U << count);
}

uint16_t func3(uint16_t x, unsigned char count)
{
 return (x >> count) << count;
}

uint16_t func4(uint16_t x, unsigned char count)
{
  return x & (0xFFFF << count);
}
```

### Expected result

`func1` and `func2` should compile to identical code. The compiler should pick the pattern that produces the smallest or fastest code for the target processor. (Clang already did this right.)

`func3` and `func4` should compile to identical code, too. If the ABI doesn't require the upper bits of the registers to be zeroed, then `func3` and `func4` code size could be as small as `func1` and `func2`.

### Current result (clang)

clang 18.1.0 and "-Os" option
(Tested in Compiler Explorer (godbolt.org))

`func1`, `func2` and `func3` produce identical code in x86-64. It seems that clang does recognize the pattern and optimize accordingly.

For x86-64 target, `((x >> count) << count)` is used.
For ARM and RISC-V targets, `((-1 << count) & x)` is used.

However clang doesn't recognize `func4` as identical to `func3`, so there are rooms to improve. (`func4` is the real case I was facing. I only need to work with a 16-bit input value and I don't want to internally promote to `uint32_t` just for optimization purpose.)

### Notes

I also reported this in GCC bug tracker:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114338

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVsmS2zYQ_Rro0iUWCVLbQQePZpjokLjKcXJ1gUCLhA0BDJaR5EO-PQWQmqFkx3GWKpVEbA-vX79ukTknW424JYsHsnicseA7Y7dP514ZizbfzBojLltCy-ED79F54EYgyR9J_mb8XubDh49jWkrNVRAIpNw5L6T2WUfKp-mhoNPVAqT2cAiaF4SubybPhO7gZYZ3zAI3QXtCNyPQ6mF4ALDog9VA6PoM8aLy6WVv5EDK3TguH65nH7_Jhv4PbM5A6DJy-iP_9ZYF3fwlEal9sfwwkCgjievEPyDwn9WYkqj-JYkvVMjPdV3X3yHE1U43Hnux4NO5R-5RgEUXlL8z4uCkZQ5MCxjHNI5dZ4ISwM2xlwrBG5ACtZecqWToDN53eF221-295J_Adwg98x6tBt8xD701InB0acUdmVKxLIyFA3P-WiFwMDZt8My2mA5xdM7YLIqxU0y3wJRFJi4gpADfSQdWtp3PXtWchlXehVV9T1gxX96YDPaHRObNwx6EQacJXXmw-HuQFtNK6Hu00EjvwAx7LbbSebQuwjYIn9EaFAmxQw3fopUEcPJzVDTyaxCYG6SKD99IVPb1rO-Ctaj9mPSoII8K3imV5qBYZ0U2AlM6f-sIpWB6L42-wq5jI0uVDbtryq9dL4K3RjRG-czYdMVX8xHZRzGmLpsEk3QZnXKXlHjteb2cL6sM9h4c4tENzhoCiAkCi9y0Oko49V-8IIZyjAuMc2OF1K263MhWGzvij-YbaRK6_vueQDeRuHQQHIrsFfDNu5_S7e_2v-zmv43A7gZ5XtxDpdo_fxVz-P7RnPAZ7STwqzOv0U9txdxESW-mUkcizkStLAKzCNaYY3KuPPbWPGMquymYdKPLY1aYQ9jDiTk4MC51m8EejFYX0IgiopyM_QQn6TtgUCznjfQgdR88PDMVMCkTK2tgf2Lap6t1TBpT6hKdcDQeR9axoZb0g488PgbnU7MY88qiUaEPtjcOv-gFLxXxs_Hopkt7YMoZsNgbG72dGorU8MNuB01owVvGP6El5bi_8753cURrQuuW86zVYXB83YT2s1SKEVq7zpw-NKHNeCtJWUtByseiqMpyPcDMxLYUm3LDZrgtVkVelcW6KmfddsFwQTdVgcVy1VRlnqNYIT1UYtEUq0WxnMktzWmVl0VVLBYrWmaHatNsNqVocLlmhxxJleORSZUp9XyMzGbSuYDb9YIuVjPFGlQuvbpQqvEEaZFQGt9k7DaemTehdaTKlXTevaJ46RVu3w5yS92O_5TD39SriS9D6aeU3VbOZVI16dlYeJYc4RmtY7Ng1fZOXem70GTcHAmtI4_xZ95b8xG5J7RO7B2hdYruzwAAAP__FrHpmw">