<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">