https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84673
Bug ID: 84673
Summary: Overcomplicated code generation for a chain of
mutually exclusive conditions
Product: gcc
Version: 7.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: zackw at panix dot com
Target Milestone: ---
This function
int has_bad_chars(unsigned char *str, __SIZE_TYPE__ len)
{
for (unsigned char *c = str; c < str + len; c++)
{
unsigned char x = *c;
if (__builtin_expect (x <= 0x1f || x == 0x5c || x == 0x7f,
0))
return 1;
}
return 0;
}
compiles with GCC 7.3.1 at -Os -march=native on a current-generation x86-64 to
has_bad_chars:
addq %rdi, %rsi
.L2:
cmpq %rsi, %rdi
jnb .L7
movb (%rdi), %al
cmpb $31, %al
setbe %cl
cmpb $92, %al
sete %dl
orb %dl, %cl
jne .L5
cmpb $127, %al
je .L5
incq %rdi
jmp .L2
.L7:
xorl %eax, %eax
ret
.L5:
movl $1, %eax
ret
It is six bytes shorter, and also I think more efficient, to generate this
instead:
has_bad_chars:
.LFB0:
.cfi_startproc
addq %rdi, %rsi
.L2:
cmpq %rsi, %rdi
jnb .L7
movb (%rdi), %al
cmpb $31, %al
jbe .L5
cmpb $92, %al
je .L5
cmpb $127, %al
je .L5
incq %rdi
jmp .L2
.L7:
xorl %eax, %eax
ret
.L5:
movl $1, %eax
ret
The same thing happens at -O2, but also a chunk of the loop body gets
pointlessly duplicated above the loop (it looks like it tried to unroll the
loop and got stuck halfway).