As observed at http://blog.regehr.org/archives/320 (example 7)
int crud (unsigned char c)
return (((((((((((int) c <= 32 || (int) c == 46) || (int) c == 44)
|| (int) c == 58) || (int) c == 59) || (int) c == 60)
|| (int) c == 62) || (int) c == 34) || (int) c == 92)
|| (int) c == 39) != 0);
Can be compiled using shift and mask test operation as:
movzbl %dil, %edi
cmpl $32, %edi
addl $-34, %edi
cmpl $64, %edi
movl $1, %eax
movl %edi, %ecx
shlq %cl, %rax
movq $0x400000017001421, %rdx
testq %rdx, %rax
movl $1, %eax
xorl %eax, %eax
Probably switch conversion pass could be responsible for this.
Note that both llvm and ICC support this optimization and it was requested by kernel folks for a while (they do so by hand)
We probably don't want to do such transformation into GIMPLE_SWITCH always, only if the number of comparisons of the same SSA_NAME is big enough and the range isn't too big.
expand_switch_using_bit_tests_p can be used if we want to limit it just to the bittest cases.
I would do the conversion always when we can turn more than one if into signle switch. Doing so reduces the amount of IL and makes program easier to analyze&opotimize. We should rely on switch expansion code doing the right thing producing back the ifs when profitable.
I know Tom de Vries is working on this problem and has a prototype patch. He'll be posting his work for 4.7.
> I know Tom de Vries is working on this problem and has a prototype patch.
> He'll be posting his work for 4.7.
Related bug: PR 14799.
(In reply to Tom de Vries from comment #5)
> > I know Tom de Vries is working on this problem and has a prototype patch.
> > He'll be posting his work for 4.7.
Does it still apply for gcc 9?
The test-case is still valid.
(In reply to Martin Liška from comment #8)
> The test-case is still valid.
Sorry, no, the issue is already solved with GCC 9.2:
crud (unsigned char c)
long unsigned int _24;
long unsigned int _32;
<bb 2> [local count: 1073741823]:
if (c_15(D) > 62)
goto <bb 4>; [50.00%]
goto <bb 3>; [50.00%]
<bb 3> [local count: 536870911]:
_16 = (int) c_15(D);
_24 = 6629387187945209855 >> _16;
_32 = ~_24;
_26 = (_Bool) _32;
if (_26 != 0)
goto <bb 4>; [20.00%]
goto <bb 5>; [80.00%]
<bb 4> [local count: 536870911]:
_11 = c_15(D) == 92;
_30 = (int) _11;
<bb 5> [local count: 1073741824]:
# iftmp.0_14 = PHI <_30(4), 1(3)>