[Bug c/51374] New: Volatile access reordered.
andyw at pobox dot com
gcc-bugzilla@gcc.gnu.org
Thu Dec 1 05:01:00 GMT 2011
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: unassigned@gcc.gnu.org
ReportedBy: andyw@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.
More information about the Gcc-bugs
mailing list