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).