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