I altered my test program to: struct sA { unsigned volatile B; unsigned volatile const C; unsigned const D; unsigned E; }; void Function( sA & A ) { A.B; A.C; A.D; A.E; } and got: .globl _Z8FunctionR2sA .type _Z8FunctionR2sA, @function _Z8FunctionR2sA: link.w %a6,#0 move.l 8(%a6),%a0 | A, A move.l (%a0),%d0 | <variable>.B, <variable>.B unlk %a6 rts As you can see, the A.B is now being loaded but not A.C. No matter where it is in the structure, I am finding that volatile const is not being loaded. My question is: How should the compiler behave with volatile const (i.e. Does the language specification require the load?)? By my understanding (weak though it may be), const only specifies that my code may not attempt to modify the object (other than initialization, construction, etc...) and volatile specifies that the object may change value without my code's intervention (and that loads are not to be optimized out). These two concepts should be orthogonal. The situation which exists in the original program is a bit more complicated. We have hardware that looks like: struct sCommand { enum eCommands { CommandAddress = 1, CommandDisable = 2, CommandIdle = 3, CommandNone = 0, CommandNop = 7, CommandReceive = 4, CommandTransmit = 5 }; enum eStates { StateDisabled = 0, StateIdle = 1, StateMaster = 2, StateSlave = 3, StateSlaveTerminated = 4, StateTransition = 5 }; unsigned : 6; bool volatile const TransmitDataFull : 1; bool volatile const ReceiveDataAvailable : 1; bool volatile const Interrupt : 1; bool volatile const Acknowledged : 1; eStates volatile const State : 3; eCommands volatile Command : 3; } Command; This is a 16 bit register in memory. The Command member is the only part which is writable, the other members are read-only (that is even if they are written, the write has no effect). However, all of the members may change in real-time without processor intervention (the Command member gets cleared when the command being executed completes). The use of volatile is to ensure that every load actually happens (since multiple bits are loaded into processor registers, without volatile the compiler may otherwise produce code that skips critical loads and uses stale data). The use of const is to smoke out programmer mistakes at compile time. The actual failing code looks like: Xilinx.Fpga.I2c.Command.Command = Xilinx.Fpga.I2c.Command.CommandNone; switch ( Xilinx.Fpga.I2c.Command.State ) { for this fragment the compiler is producing: move.b Xilinx+139,%d0 moveq.l #-8,%d1 and.l %d1,%d0 move.b %d0,Xilinx+139 move.b %d0,%d2 lsr.l #3,%d0 moveq.l #7,%d4 and.l %d4,%d0 moveq.l #4,%d1 cmp.l %d0,%d1 jbcs .L322 Xilinx+138 is the address of the register. As you can see the compiler is loading the lower 8 bits of the register, altering it, and storing the result. Unfortunately, it then uses this result rather than reloading the register to do the State switch. The program is actually failing once every few million events because a hardware state change happens after the Command write that the switch misses. While I can, and must, change my volatile const(s) to volatile(s) and trust that none of the programmers will attempt an alteration, it seems that the language has the features to do better. I would like to generate a PR but I'm looking for confirmation that my understanding about volatile const's semantics are correct. -----Original Message----- From: gcc-help-owner@xxxxxxxxxxx [mailto:gcc-help-owner@xxxxxxxxxxx] On Behalf Of Daniel Berlin Sent: Friday, August 26, 2005 6:04 AM To: Steve Zook Cc: gcc-help@xxxxxxxxxxx Subject: Re: volatile const structure members in C++ On Thu, 2005-08-25 at 21:24 -0700, Steve Zook wrote: > Using m68k-elf-gcc with either revision 3.3.3 or 3.4.4, I compile the > following test program (as a C++ program) at -O2 to an object file: > > > struct sA { unsigned volatile const B; > unsigned volatile C; > unsigned const D; > unsigned E; }; > void Function( sA & A ) { A.B; A.C; A.D; A.E; } > > > The object file I get looks like (edited for brevity): > > .globl _Z8FunctionR2sA > .type _Z8FunctionR2sA, @function > _Z8FunctionR2sA: > link.w %a6,#0 > move.l 8(%a6),%a0 | A, A This is a load of A.B. It's the first member of the structure, and thus, is at offset 0, and is also known as "A". I imagine if you rearrange the struct so that B and C are farther into the struct (IE add a dummy member in front, etc), you'd see the more explicit loads you are looking for. > move.l 4(%a0),%d0 | <variable>.C, <variable>.C > unlk %a6 > rts > > I was expecting that A.B and A.C would both generate loads since they > are both volatile, and that A.D and A.E would not, but only A.C loads. > > Have I misunderstood how volatile const should work, or is this a bug > I should submit? > >