Volatile bug in unmaintained GCC 436 and 447

Paulo J. Matos paulo@matos-sorge.com
Thu Jul 12 10:53:00 GMT 2012


Hello,

As far as I know 4.3 and 4.4 are no longer maintained and 4.3.6 and 
4.4.7 were the last of their respective lines however if someone is kind 
enough to look at the following, I would be extremely grateful. I found 
a bug in 4.3.6 and 4.4.7 fixed in 4.5.0 but I am having a hard time 
pinpointing the fix.

For the following code:
volatile unsigned int some_reg1;
volatile unsigned int some_reg2;

volatile unsigned int another_reg1;
volatile unsigned int another_reg2;

void poke_and_wait(int use_reg1)
{
   volatile unsigned int *s_reg;
   volatile unsigned int *a_reg;

   if (use_reg1)
     {
       s_reg = &some_reg1;
       a_reg = &another_reg1;
     }
   else
     {
       s_reg = &some_reg2;
       a_reg = &another_reg2;
     }

   *s_reg = 0x1;

   while (*a_reg & 0x2) ;
}

GCC 4.4.7 generates (4.3.6 generates equally incorrect code) with -Os:
poke_and_wait:
.LFB0:
         .cfi_startproc
         testl   %edi, %edi
         je      .L2
         movl    another_reg1(%rip), %eax
         movl    $some_reg1, %edx
         jmp     .L3
.L2:
         movl    another_reg2(%rip), %eax
         movl    $some_reg2, %edx
.L3:
         movl    $1, (%rdx)
         andl    $2, %eax
.L4:
         testl   %eax, %eax
         jne     .L4
         ret
         .cfi_endproc
.LFE0:
         .size   poke_and_wait, .-poke_and_wait

The problem here is that *a_reg is not reloaded in the loop of .L4 -> 
.L4 therefore being an infinite loop.

With GCC 4.5.0:
poke_and_wait:
.LFB0:
         .cfi_startproc
         testl   %edi, %edi
         movl    $another_reg2, %eax
         movl    $another_reg1, %edx
         cmove   %rax, %rdx
         movl    $some_reg2, %ecx
         movl    $some_reg1, %eax
         cmove   %rcx, %rax
         movl    $1, (%rax)
.L3:
         movl    (%rdx), %eax
         testb   $2, %al
         jne     .L3
         ret
         .cfi_endproc
.LFE0:
         .size   poke_and_wait, .-poke_and_wait

Here is seems ok since (%rdx) is reloading the value.

I have been looking at the database but I can't pinpoint where this was 
fixed. I am open to suggestion as to where this bug was fixed (revision, 
date, file, ... anything helps).

Why?... I would like to port the fix back to 4.3.

Cheers,

-- 
PMatos




More information about the Gcc mailing list