https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114490
Bug ID: 114490
Summary: Optimization: x86 "shl" condition codes never reused
Product: gcc
Version: 13.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: Explorer09 at gmail dot com
Target Milestone: ---
This seems to happen with x86 target only.
For the example code below, I can use the SF (sign flag) after a left shift
(<<) operation, but somehow I cannot make GCC reuse the condition code of a
"shl" instruction. It always generates an unnecessary "testl %edx, %edx" before
the conditional jump.
This is one case where the condition code of a bit shift can be useful. I know
in the ARM target of GCC, the condition code is reused after the shift.
```c
#include <stdbool.h>
#include <stdint.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 gcc with "-O3" option
(Actually I tested in Compiler Explorer (godbolt.org))
```x86asm
my_isxdigit:
movl %edi, %ecx
movl $2113994688, %eax
sall %cl, %eax
movl %eax, %edx
xorl %eax, %eax
testl %edx, %edx
jns .L1
shrb $4, %cl
movl $436207616, %eax
sall %cl, %eax
shrl $31, %eax
.L1:
ret
```
Possible shorter code:
```x86asm
my_isxdigit_2:
movl %edi, %ecx
xorl %eax, %eax
movl $2113994688, %edx
sall %cl, %edx
jns .L2
shrb $4, %cl
movl $436207616, %eax
sall %cl, %eax
shrl $31, %eax
.L2:
ret
```