/*
the following case produces suboptimal code:

everything compiled with -O3 only
*/

extern char testcase(int* d)
{
        int w23;
        w23  = d[2] < d[3];
        w23 &= d[3] < d[2];

        return w23;
}

/*
4.1.0 20050410 m68k-aout (cygwin host)

testcase:
        link.w %fp,#0
        move.l 8(%fp),%a0
        move.l 8(%a0),%a1
        move.l 12(%a0),%d1
        cmp.l %a1,%d1
        sgt %d0
        extb.l %d0
        neg.l %d0
        cmp.l %a1,%d1
        slt %d1
        extb.l %d1
        neg.l %d1
        and.l %d1,%d0
        extb.l %d0
        unlk %fp
        rts


notice that the same cmp.l is executed 2 times
the same happened on the 3.4.1 i386 cygwin build:

3.4.1 x86 cygwin
_testcase:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        movl    12(%eax), %edx
        movl    8(%eax), %ecx
        xorl    %eax, %eax
        cmpl    %edx, %ecx
        setl    %al
        cmpl    %edx, %ecx
        setg    %dl
        movzbl  %dl, %edx
        andl    %edx, %eax
        ret

the x86 build for 4.1.0 optimized the 2. cmp away but...

4.1.0 20050410 cygwin
_testcase:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        movl    8(%eax), %edx
        movl    12(%eax), %eax
        cmpl    %eax, %edx
        setl    %cl
        setg    %al
        movzbl  %al, %eax
        andl    %ecx, %eax
        leave
        ret


if we add a second block to make it more complex it returns.
*/

extern char testcase2(int* d)
{
        int w23,w13;
        w23  = d[2] < d[3];
        w23 &= d[3] < d[2];

        w13  = d[1] < d[3];
        w13 &= d[3] < d[1];

        return w23|w13;
}

/*

4.1.0 20050410 cygwin
_testcase:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        pushl   %ecx
        movl    8(%ebp), %eax
        movl    8(%eax), %edx
        movl    12(%eax), %ecx
        cmpl    %ecx, %edx              ;1
        setl    %bl
        movl    4(%eax), %eax   ;2
        cmpl    %eax, %ecx
        setg    -5(%ebp)
        cmpl    %ecx, %edx              ;1
        setg    %dl
        andl    %ebx, %edx
        cmpl    %eax, %ecx              ;2
        setl    %al
        andb    -5(%ebp), %al
        orl     %edx, %eax
        movsbl  %al,%eax
        popl    %edx
        popl    %ebx
        leave
        ret


note: if in these redued function we replace the 
w23 &= d[3] < d[2];
with 
w23 = w23 && (d[3] < d[2])

we get the "correct"

return false;

but in my more complex project these double compares still 
show up even with &&;
*/

-- 
           Summary: missed-optimization setcc boolean compare
           Product: gcc
           Version: 4.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: rtl-optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: kellivoss25 at yahoo dot de
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21991

Reply via email to