http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51374
Bug #: 51374 Summary: Volatile access reordered. Classification: Unclassified Product: gcc Version: 4.6.2 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: an...@pobox.com Host: i386-redhat-linux Target: avr Created attachment 25964 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25964 .i file demonstrating the bug. It appears that if the compiler feels able to use the sbis instruction, the ordering of accesses no longer respects the volatile keyword. In attached test case, the status register (UCSR0A) needs to be read before the data register (UDR0) in order to be valid. The assembler output shows that the sbis instruction is used to test UCSR0A after UDR0 has been read. Decoupling assignment and declaration has no effect on this behaviour. Selected highlights from the avr-gcc mailing list thread leading to this bug report: Well, in avr.md we have ;; Lower half of the I/O space - use sbic/sbis directly. (define_insn "*sbix_branch" [(set (pc) (if_then_else (match_operator 0 "eqne_operator" [(zero_extract:HI (mem:QI (match_operand 1 "low_io_address_operand" "n")) (const_int 1) (match_operand 2 "const_int_operand" "n")) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] "(optimize > 0)" "* return avr_out_sbxx_branch (insn, operands);" The problem is that there is (mem:QI (match_operand 1 "low_io_address_operand")) instead of (match_operand:QI 1 "low_io_memory_operand")) Actually, there is no low_io_memory_operand predicate, but if there was one it would solve this problem. The reason is that a plain mem is not sensitive to volatile (resp. volatile_ok) but a memory predicate is. It was written that way because otherwise, the pattern would *never* match because the only reason to have it is to produce SBIS/SBIC which only work on I/O which is volatile. I am really unsure of combine can be blamed here because the operand that it moves over the other volatile access (UDR0) is just an integer, namely a low_io_address_operand one. I'd suggest to ask in address@hidden if insn combine may do it. If yes, we are really in trouble because there is no obvious way how avr.md can fix it without kicking out SBIS/SBIC/SBI/SBC.