[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