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

    <tr>
        <th>Summary</th>
        <td>
            Optimization: x86 "shl" condition codes can be reused
        </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>
    This example codes shows a possible reuse of the SF (sign flag) after a left shift (<<) operation. But Clang seems to always generate a 'test' instruction after the shift; it doesn't reuse the condition code of the 'shl' when possible.

(Note: [I also reported this issue in GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114490).)

```c
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

bool my_isxdigit(unsigned char ch) {
  uint32_t mask1 = 0x7E00FFC0;
  // Prevent the compiler from transforming the constants.
  // Suppose we have to use them as written.
  __asm__ ("" : "+r" (mask1));

  if (!((mask1 << (ch & 0x1F)) >> 31))
    return false;

  uint32_t mask2 = 0x1A << 24;
  __asm__ ("" : "+r" (mask2));

  if (!((mask2 << (ch >> 4)) >> 31))
    return false;

  return true;
}
```

x86-64 Clang with "-O3" option
(Actually I tested this in Compiler Explorer (godbolt.org))

```x86asm
my_isxdigit:
  movl   %edi, %ecx
 movl   $2113994688, %eax
  shll   %cl, %eax
  testl  %eax, %eax
  js .LBB0_2
  xorl   %eax, %eax
  retq
.LBB0_2:
  movl $436207616, %eax
  shrl   $4, %ecx
  shll   %cl, %eax
  shrl   $31, %eax
  retq
```

Possible smaller code (I show this tweak specifically for Clang; in the [GCC bug report](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114490) I wrote an even smaller one):

```x86asm
my_isxdigit_2:
  movl   %edi, %ecx
 movl   $2113994688, %edx
  xorl   %eax, %eax  # Sets SF to 0 if 'shll' does not affect flags.
  shll   %cl, %edx
  js     .L1
 retq
.L1:
  movl   $436207616, %eax
  shrl   $4, %ecx
  shll %cl, %eax
  shrl   $31, %eax
  retq
```

The FLAGS register might be unmodified if the shift count is zero (i.e. value in `%cl` register is zero), but optimization is still possible if we set the FLAGS to a known state prior to the shift operation. (Thanks GCC developers for hinting this for me.) For example, `xorl %eax, %eax` sets CF and SF bits to 0, so the `my_isxdigit_2` code can work.

This optimization might require tracking on whether the FLAGS states are known. If this is impossible internally in LLVM, feel free to close this report.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V91u6zgOfhrlhqhhy47jXOSiSZuDAt2dAXqwt4Fs07amspSR5CY9T7-gbKfpz9mZ3dkpAtcRRYo_n8gvwjnZasQNW27Z8m4hBt8Zu7k_H5WxaOP1ojT16-Z7Jx3gWfRHhVCZGh24zpwcCDga52SpECwODsE04DuEpz0wXpBtaJRoGV-DaDxaEKCw8eA62XjawtIdffgazBGt8NLoCLaDh50SugWH2DvwBoQ6iVcHLWrahSCA8ZVH5xlfgdTO26Ei5ekY8iGcwdItSA-1QadJY3KT5JXRtQw6FNHsOeMr1ymyeupQX8KLWHzH4tvpyYt_Go8svQW23D6AUM6AxaOxHmvwlCzp3IAgNXzb7djyjvGi8_7oWHrL-J7xfVtVUauHyNiW8X05tD-kUoLxPeX1UA5tVLWSpXtZs_QuSbJsHTO-jhhfv3Mkj8dPNTuWSl2poUZg6c75ujRGRR1L738il9r_R7G5loYnWYT-9SDduZat9IwXgw4gqqHqhIWqo2qy1XbcDzBI7VN-8NAL95wAS-8gPq_u43i_38UsvewbEwO_WnxB7acS9Uep0EJjTQ_eCu0aY3up27mCzgvtXfTBxtNwPBqHcELoxAsSgKaq9yAcnKz0HvVF63AQrj8cAh45Z5xDKC29bm34yovgPKWfry8-z_qyGVWT8CzmOAnZJKg6YDyH-JzsRwNAOU3vIZ0NTnYALPrBamiEcvjpmHeJ5FMik9v5JJ5dJfPPhsT_fEj8Q0hjDNlfCmkSejtcyVZ3H9B9rXMu8ps8m9rDSXrKLb_5JaWYzJGu8-WO3lZ-EEq9wgNQp7hcTQ27GVdzo6OYWlOXRvnxSq5_dtPORS5cPy5eX4P0ElNvXhQQFJdYS8Z34a06T-KLNONJkq7XWV4U8yYxbwLXqclGpT5LKRoF8-In8W8OosftNj7weeVs7OzSVwoW_e_j-6z3IRrGsyzNebzKk_wrZyfrWfYp3D-I5E2VgPNzv76Ewq_z6HG9UFTN0McZLx7CdBqr7U8onsEdsZKNrAIcGmNH_IThoMe2v9x-2-2gHNqpkf__mjY8wMkamlkaqLVd3DUaw9W7_W-A9rk4_xPU6vMfYINWUnhC72iYewPx2BNoOobxSCMVtPEgmgYrH-b8WyP-quz1NULpL3pMppVrBCZfBfjX8Pd3oO97h7B_vP32BBZb6Yh19LLtPJQIg-5NLRuJNSXtQkagMoP2IB38QGsIqTLCCF6EGrkCnRA8zeM3o9Pu0JIIoD60uV7-CGSJxM5Lpd6ImGxo7jkcR-joIjEoeNbmpMF54k9HK42l5TfnrggY48X3TuhnR_QFanxBRVIXrk4ntR8nsBwXeiReAntjZ44YkpnHAVqfmk4ek3MOdnsQuiZ0ldIHkhfTLjf6xPL4PerzeLzfldBwMvY5el8M6d7nZayFxd8HaZGoQ_VMThtNvM53E0ccsxNS4kBYHHMUwUMz0ziQ_VtmtUerQw-RGh4f__UPcrhBVNBYDDSjUiYQDemmPhIt6k1ar9O1WOAmWSXJMi3iZb7oNpUoU_rSNKmohEiTJks5L-smXuUZNuVCbnjMszjlqyRJsngdFdjUYpk1mDVF3KQly2LshVSRUi89daVFoJ2bIl8VxUKJEpULzJ5zjaeRkxIFWN4t7IZ0bsqhdSyLlXTevVnx0ivc_HKVTiIP5yKnWRvYMf_Anl0oSzn9CqgXg1WbD71T-m4oo8r0jO_ppOnfzdGa37DyjO-Df47xffD_3wEAAP__tEa1mg">