https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104800
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Martin Uecker from comment #8) > The standard specifies in 5.1.2.3p6 that > > "— Volatile accesses to objects are evaluated strictly > according to the rules of the abstract machine." > > and > > "This is the observable behavior of the program." > > > If a trap is moved before a volatile access so that the access never > happens, than this changes the observable behavior because the volatile > access was then not evaluated strictly according to the abstract machine. Well, the volatile access _was_ evaluated strictly according to the abstract machine. Can't your argument be stretched in a way that for global = 2; *volatile = 1; your reasoning says that since the volatile has to be evaluated strictly according to the abstract machine that the full abstract machine status has to be reflected at the point of the volatile and thus the write of the global (non-volatile) memory has to be observable at that point and so we may not move accesses to global memory across (earlier or later) volatile accesses? IMHO the case with the division is similar, you just introduce the extra twist of a trap. The two volatile accesses in your example are still evaluated according to the abstract machine, just all non-volatile (and non-I/O) statements are not necessarily.