Udo said:
On Mon, 07 Aug 2006 14:43:47 +0100 Chris Dollin (CD) wrote:
CD> Udo A. Steinberg wrote:
CD>
CD> > Or, in other words, is a compiler allowed to speculatively fetch a and b
CD> > from memory and then assign one of them to x based on the condition?
CD>
CD> Yes, if you can't tell the difference [with conforming C code]; this is the
CD> "as if" rule. The standard specifies the semantics, and the implementation
CD> can do anything that provides the same result so long as its sneakiness
CD> is invisible.
How well defined is "invisible sneakiness"?
Almost exactly, since it's fully defined by the language specification. Any
two pieces of behavior that have equal semantics according to the standard
are interchangeable, even if they are observably different. The key is that
"observation" happens on the concrete machine, while the standard only
defines semantics in terms of an abstract machine.
In my case "a" is only mapped in virtual memory if the condition is true.
Otherwise access to "a" causes a page fault. Here the compiler sneakiness
becomes visible to the user. However, if the compiler can always assume
that all memory is mapped, then the sneakiness is indeed invisible.
The compiler is allowed to do this, according to the standard, even if the
page fault involved releasing a carrier pigeon that flies to Mount
Kilimanjaro to retrieve the information you requested -- the standard does
not say how memory retrieval is implemented, in particular not what its
performance characteristics are. Of course, implementations are expected to
be "reasonable" to give the poor programmer a fighting chance.
The sort of guarantees you're looking for require intimate knowledge of the
platform(s) you're compiling on (which includes the compiler). Aside from
"volatile", you have little to no way to reliably influence the compiler's
behavior with regards to memory access, and even "volatile" has its fuzzy areas.
You can try to make prefetching the values as difficult or unattractive as
possible, you can try disabling optimization for this particular piece of
code, you can try compiler-specific extensions, or you could write the parts
you don't want the compiler to ever optimize in assembler. All of these
approaches require an amount of nonportable code, but since you're
specifically dealing with virtual memory that you have some sort of
interface to, this shouldn't be a big problem. Just make sure you document
clearly what you're trying to achieve in each instance, so your code won't
mysteriously break when the platform changes and human beings won't undo
your carefully crafted compiler conning.
S.