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

            Bug ID: 58546
           Summary: volatile bug and also larger code at -Os
           Product: gcc
           Version: 4.9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: regehr at cs dot utah.edu

I believe that gcc r202854 for x86-64 Linux miscompiles the program below at
-Os.

int a;
volatile char b = 1;
short c[] = { 0, 0, 0, 0, 0, 0, 1 };
int main() {
  for (; a >= 0; a--)
    c[6]++;
  return 0;
}

The compiler output is:

main:
    movl    a(%rip), %eax
    movl    %eax, %ecx
    addl    c+12(%rip), %ecx
.L2:
    movl    %ecx, %edx
    subl    %eax, %edx
    testl    %eax, %eax
    js    .L5
    decl    %eax
    jmp    .L2
.L5:
    movl    %eax, a(%rip)
    movw    %dx, c+12(%rip)
    xorl    %eax, %eax
    ret

I believe that 32-bit load of c[6] at c+12(%rip) is incorrect as it causes a
spurious load from volatile variable b. This kind of spurious load can cause
problems for low-level code where reads have side effects such as a page fault
or hardware register access.

In contrast, the -O2 code is smaller and properly accesses c[6] using a 16-bit
load and store:

main:
    movl    a(%rip), %eax
    testl    %eax, %eax
    js    .L2
    addw    c+12(%rip), %ax
    movl    $-1, a(%rip)
    addl    $1, %eax
    movw    %ax, c+12(%rip)
.L2:
    xorl    %eax, %eax
    ret

Reply via email to