http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56098
Bug #: 56098 Summary: conditional write through volatile pointer produces unintended read Classification: Unclassified Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: wer...@almesberger.net If compiled with -O2 or greater and without -fno-strict-aliasing, the following code volatile int *ptr; void problem(int flag) { *ptr = 1; if (flag) *ptr = 2; } produces an unintended read, as if the "if" statement had continued with else *ptr = *ptr; Code generated by gcc 4.7.2 on Ubuntu on x86-64 when invoked with gcc-4.7 -Wall -Wextra -O2 -S bug.c ... problem: .LFB0: .cfi_startproc movq ptr(%rip), %rax testl %edi, %edi movl $2, %edx movl $1, (%rax) jne .L2 movl (%rax), %edx <<< unexpected .L2: movl %edx, (%rax) ret .cfi_endproc ... This happens with - gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 for x86-64, - gcc-4.7 (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2 for x86-64, - mipsel-openwrt-linux-gcc (Linaro GCC 4.6-2012.02) 4.6.3 20120201 (prerelease) for MIPS, and I've had someone confirm it for an ARM target (without further details) as well. -Os instead of -O2 has the same effect. The unintended read disappears if optimizing with -O1 or less, or with -fno-strict-aliasing. This bears a striking resemblance to Bug 15456 and maybe Bug 5395, except that these were for C++ while this is plain C.