In the example below f1 and f2 are equivalent functions differing only by the order of conditions in if(): y && !(x & 1) versus !(x & 1) && y. There are two lost optimization opportunities here: gcc does not try to pick an order of conditions which is better, and in both cases it does not use the fact that (x & 1) at this point is available as a carry bit.
void a(unsigned); void f1(unsigned x) { unsigned y = x / 2; if (y && !(x & 1)) a(y); } /* compiled with -Os -fomit-frame-pointer on x86_64: 20 bytes f1: movl %edi, %eax shrl %eax je .L7 andb $1, %dil jne .L7 movl %eax, %edi jmp a .L7: ret */ void f2(unsigned x) { unsigned y = x / 2; if (!(x & 1) && y) a(y); } /* 18 bytes f2: movl %edi, %eax shrl %edi testb $1, %al jne .L3 testl %edi, %edi je .L3 jmp a .L3: ret */ /* Handwritten assembly: 12 bytes f3: shrl %edi jc .L77 jz .L77 jmp a .L77: ret */ -- Summary: Suboptimal optimization: after x / 2 carry flag == x & 1 Product: gcc Version: 4.4.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: vda dot linux at googlemail dot com GCC build triplet: x86_64-redhat-linux GCC host triplet: x86_64-redhat-linux GCC target triplet: x86_64-redhat-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42200