On Apr 4, 7:47 pm, Tim Rentsch <
t...@alumni.caltech.edu> wrote:
> Joshua Maurice <
joshuamaur...@gmail.com> writes:
> > On Mar 27, 10:47 pm, Tim Rentsch <
t...@alumni.caltech.edu> wrote:
> >> We aren't allowed
> >> to observe what the actual machine does _between_ accesses to
> >> volatile objects, but we are allowed to observe the state
> >> of the actual machine at each point _of_ a volatile access, and
> >> the actual machine state must match those things that must be
> >> true in the abstract machine.
>
> > I think this is patently silly. Are you saying that you can't do
> > basic optimizations like common subexpression elimination, power
> > reductions, and so on when volatiles are involved? You can't examine
> > the state of an object if the object is optimized out of existence.
>
> I think you're overstating the case. The situation with volatiles
> isn't really very different from what happens with calls to external
> functions. Basically you can do all the optimization you want up
> to the point of the function call, but then everything has to "look
> right" when the function is called. The presence of function calls
> reduces the opportunity for optimization but certainly doesn't
> eliminate it. The effect with somewhat larger with volatile, but
> not at all totally inhibiting.
Let's be clear. Consider:
int main()
{
int volatile x;
int y;
y = 1;
x = 1;
y = y * 2;
return y;
}
By your argument, that program cannot be transformed by the compiler
to:
int main()
{
int volatile x;
x = 1;
return 2;
}
Which I think is highly silly, and (in my admittingly near complete
ignorance of actual implementations on this issue), I doubt that any
commercial implementation shares your view.
As a trite test, I just tested this on gcc version 4.1.2 20080704 (Red
Hat 4.1.2-44). I took both programs, compiled as:
gcc -O2 source.c
and did a binary diff on the output executable. Same contents.
(Simpler than comparing the assembly in this case.) At least this
version of gcc shares my views.
Do you really want to disallow that particular optimization, and
similar optimizations? Reference escape analysis can show that an
optimization on a local variable is safe to do across a function call,
function calls can be expanded inline, several implementations even do
link-time inlining and further optimization, and so on. With that in
mind, your proposed volatile semantics are actually a lot more
restrictive than function calls.
> > I hesitate to even contemplate the implications this would have for
> > threaded programs. Your interpretation more or less outlaws all
> > optimizations for a program with threads.
>
> Nonsense. Programs with threads don't have to use volatile, and
> volatile doesn't make any guarantees about inter-thread semantics.
> Certainly it _could_ make a difference in _some_ implementation,
> but equally certainly there is no reason it _must_ make a
> difference in _all_ implementations. Because what constitutes
> volatile access is implementation-defined, it's not especially a
> good choice for effecting inter-thread synchronization anyway, but
> even assuming it is used, the costs will likely be due mostly to
> putting in the necessary memory barriers (which are substantial),
> not to the comparatively minor effect of less freedom in
> optimization choices.
I'm sorry, I wasn't clear enough in my problem statement. I agree that
volatile as spec-ed, especially w.r.t. C1x (has the name been
formalized yet? sorry), is useless for inter-thread communication. (As
you note, perhaps an implementation could make stronger guarantees,
but the C standard does not give you enough on its own.)
That was not my point at all.
You made the interesting claim that at any volatile read or write, you
could examine the entire machine, and ensure that the abstract
semantics are followed. The logical extension IMHO would be to examine
the states /of other threads/. And as other threads execute
asynchronously, all optimizations are basically prohibited in the face
of a single volatile operation.
Of course, I think this is all rather academic, because I subscribe to
Marcin Grzegorczyk's view. I believe this is the consensus view IMHO.
The only guarantees you have are the specified visible behavior of the
abstract machine. This includes volatile operations, IO, and the
return value of main. No guarantees are given at all about the values,
or even existence, of non-volatile objects, at all, except insofaras
the behavior is visible from the aforementioned visible behavior.