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

Reply via email to