On 07/01/12 18:18, Peter Bigot wrote: > On Sat, Jan 7, 2012 at 10:28 AM, Grant Edwards > <grant.b.edwa...@gmail.com> wrote: >> On 2012-01-07, Peter Bigot<big...@acm.org> wrote: >>> On Sat, Jan 7, 2012 at 9:00 AM, Grant Edwards<grant.b.edwa...@gmail.com> >>> wrote: >>> >>>> It's quite possible that the 4.x compiler is more aggressive about >>>> moving stuff around. ?When working on low level stuff like an MSP430, >>>> I pretty much always have my Makefiles set up to generate mixed >>>> C/assmebly language listings so that it's easy to keep an eye on what >>>> the compiler is doing. ?One advantage of that is that you quickly >>>> learn what C constructs are handled efficiently by the compiler wand >>>> what aren't -- you learn that the smallest, fastest way to do things >>>> in C on an MSP430 is not the same as on an AVR. >>> >>> The 4.x compilers (especially 4.6.x) do optimize much more >>> aggressively, but if you use the defined peripheral registers like >>> P2OUT mspgcc had better not re-order them across sequence points, >>> since those are marked volatile. If you do see something like this, >>> it's almost certainly a bug and I'd appreciate it being reported on >>> the SF tracker. >> >> However the "test code" might be non-volatile, and as such GCC is >> still free to move it outside the set/clear pair (AFAICT). The GCC >> documentaion I've found appears to indicate that the restriction on >> moving code across sequence points only affects volatile accesses. >> Quoting from >> http://gcc.gnu.org/onlinedocs/gcc-4.5.3/gcc/Volatiles.html#Volatiles >> >> The minimum either standard specifies is that at a sequence point >> all previous accesses to volatile objects have stabilized and no >> subsequent accesses have occurred. >> >> Note that the GCC docs only say that _volatile_ accesses can't be >> moved across sequence points. More searches reveal similar statements >> along with a few seemingly well-informed postings where it is >> explicitly stated that non-volatile accesses may be moved across >> sequence points. >>
Not only /may/ actions (calculations, non-volatile read/write accesses, etc.) be moved across volatile accesses, but it has been seen to happen in practice, causing some confusion to posters on lists like this and the equivalent avr-gcc mailing lists. In particular, people seem to get quite upset when the compiler moves code back and forth across interrupt disable/restore pairs! Memory barriers help - they create a sequence point which read and outstanding write accesses can't move across. But even they will not limit the movement of calculations and work involving only local variables. I don't know of any way to guarantee that without using artificial volatile accesses. >> For example from http://blog.regehr.org/archives/28 (which appears to >> be a rather well-informed article): >> >> Summary: Most compilers can and will move accesses to non-volatile >> objects around accesses to volatile objects, so don't rely on the >> program ordering being respected. >> >> I don't know if it's still an issue, but at one point he mentions a >> "volatile" bug in MSP430: >> >> Compilers are not totally reliable in their translation of accesses >> to volatile-qualified objects. I've written extensively about >> this subject elsewhere, but here's a quick example: >> >> volatile int x; >> >> void foo (void) { >> x = x; >> } >> >> The proper behavior of this code on the actual machine is unambiguous: >> there should be a load from x, then a store to it. However, the port >> of GCC to the MSP430 processor behaves differently: >> >> $ msp430-gcc -O vol.c -S -o - >> foo: >> ret >> >> [I don't know which version of mspgcc that refers to, and it's not >> really related to our topic but it does lead me to believe that the >> author knows what he's talking about.] > > I believe John was referring to an early patch set applied to > LTS-20110716. In fact, he filed that as a bug > (https://sourceforge.net/tracker/?func=detail&aid=3399383&group_id=42303&atid=432701), > and it was discussion with him that led me to revisit the issue and > fix the underlying implementation, even though I chose not to fix that > particular problem for that release. See the comments in the tracker > entry for more details. > >> Anyhow.... I can't find anywhere in GCC docs that say non-volatile >> accesses can't be moved across sequence points or volatile accesses. >> If sequence points and volatile accesses only constrain ordering of >> accesses to volatile objects, and what you're timing doesn't involve >> volatile objects, then adding sequence points doesn't matter. >> >> However, adding a memory barrier ought to do the trick. I think. > > Yes, today I think you're right. In fact, that's what I thought back > in early December when I added cycle timing to test430 and found a > situation where the compiler helpfully moved the test code out from > between the start/stop counter reads. I did something that stopped > that from happening, though I don't remember what; it wasn't a memory > barrier. > > Later in December, the topic arose again in the context of the thread > at http://gcc.gnu.org/ml/gcc/2011-12/msg00008.html, during which > discussion I became convinced any such move was a compiler error, > apparently because I mis-read Richard Guenther's response in > http://gcc.gnu.org/ml/gcc/2011-12/msg00026.html. The discussion there > ultimately revealed an underlying gcc bug that will eventually be > fixed in a 4.7.x release, so confusion about the issue is common even > among those who are expected to know better. > > I haven't seen the problem again with mspgcc, but only because I > haven't since done timing except around calls to an external function. > gcc presumably treats that as a barrier since it can't tell what > happens during that call, but I again believe it can happen with > inline code and your warning is well-taken. > >> Pointers to GCC docs actually stating what to expect would be >> most welcome... > > The current version of what you cited > (http://gcc.gnu.org/onlinedocs/gcc/Volatiles.html) is the best I know > of, and indeed a full memory barrier expressed as: > > asm volatile ("" : : : "memory"); > > is what GCC promises to obey. Given mspgcc's old practice of > bypassing gcc's volatile validation infrastructure I can't make any > promises that even that will work in any release prior to the 4.6.x > development series. > Such a memory barrier will (or at least should!) block the movement of any reads or writes to memory across the barrier. But it will not prevent the movement of other code. Also remember that a barrier like this can be expensive - more so on targets with more registers, and with more complex code - since it also means the compiler must "forget" anything it had loaded from memory beforehand, even if it is still valid. It would be nice if there were some sort of finer-grained memory barrier - perhaps to say that all writes had to be completed, but reads could be moved, or to allow movement in one direction but not the other. > Thanks for making me revisit this again so I could reset my > understanding. When I'm working on it I usually have it right; it's > the off-hand comments when I'm focused on some other problem that get > me in trouble. > > Peter > ------------------------------------------------------------------------------ Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex infrastructure or vast IT resources to deliver seamless, secure access to virtual desktops. With this all-in-one solution, easily deploy virtual desktops for less than the cost of PCs and save 60% on VDI infrastructure costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox _______________________________________________ Mspgcc-users mailing list Mspgcc-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mspgcc-users