[Bug c/12799] New: cmov is confused by a intervening inc that bashes flags.

pratap at vmware dot com gcc-bugzilla@gcc.gnu.org
Mon Oct 27 23:21:00 GMT 2003


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

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

           Summary: cmov is confused by a intervening inc that bashes flags.
           Product: gcc
           Version: 3.3
            Status: UNCONFIRMED
          Severity: critical
          Priority: P1
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: pratap at vmware dot com
                CC: gcc-bugs at gcc dot gnu dot org

The following program returns 1 (denotes failure), instead of 0 (which
denotes success) when compiled with the following compiler flags,
using gcc 3.0.3, but passes with the same flags on gcc 3.3. 

I'm still filing this as a bug on gcc 3.3 since all my bugzilla searches 
did not convince me that the bug has indeed been fixed in 3.3. 

Here are the flags: 
    -O2 -g3 -march=i686 -fno-strict-aliasing  -pipe
    -mpreferred-stack-boundary=2 -fno-strict-aliasing 
    -march=i686 -mcpu=i686 -malign-jumps=2 -malign-functions=2
    -malign-loops=2 -mregparm=3 -Wmissing-prototypes'

________________________________________________________________________

int loo = 1;

__inline__ char InlineFunc(void);
int FooBar(void);

__inline__ char InlineFunc(void)
{
   return __builtin_expect(!!(loo == 1), 1);
}

int FooBar(void)
{
   int i;
   int var1 = InlineFunc() ? 2046 : 1023;
   int var2 = InlineFunc() ? 512 : 1024;

   for (i = 0; i < var1; i++) {};
   if (InlineFunc() && var2 != 512) {
      return 1;
   }
   return 0;
}

int main() {
   return FooBar();
}

________________________________________________________________________


Here is the assembly generated by the 3.0.3 compiler: 

       <stuff snipped> 

        movl    $1023, %eax
        movl    $2046, %ecx
        movl    %esp, %ebp
        pushl   %ebx
        cmpl    $1, %edx
        movl    $512, %ebx
        cmovne  %eax, %ecx
        incl    %eax                    <<<< bashes flags
        cmovne  %eax, %ebx              <<<< needs those old flags!
        
       <stuff snipped>

It seems that an "add %eax = %eax + 1" in the intermediate graph
was replaced incorrectly with an "inc %eax".

When I try this with the 3.3 compiler, I see: 

        sete    %al
        testb   $1, %al
        movl    $1023, %eax
        cmove   %eax, %ecx
        cmpl    $1, %edx
        sete    %al
        testb   $1, %al
        movl    $1024, %eax   <<< this is fine, it doenst bash flags. 
        cmove   %eax, %ebx
        testl   %ecx, %ecx

It is comforting to know that gcc 3.3 does not exhibit problem. What I
want to know is if 3.3 really fixes the problem, or is it some accident
of compiler phase ordering. I did a deep search of the gcc.gnu.org
bugzilla database but did not find any reported bugs that seemed like
this one. If I have missed it, could you point me to a bug report, bug
id? 

We would like to move to 3.3 with the confidence that the bug has been
fixed, or else we may be forced to turn off cmov synthesis, which will
be unfortunate since it is a good performance win.

Please advice.



More information about the Gcc-bugs mailing list