Volatile MEMs in statement expressions and functions inlined as trees

Linus Torvalds torvalds@transmeta.com
Thu Dec 13 13:56:00 GMT 2001


On Thu, 13 Dec 2001, Richard Henderson wrote:
> This I do not agree with.
>
> > 	See also existing gcc practice, see the example of code generated
> > 	for just a plain "p" when "p" is volatile.
>
> Plain "p" is implementation defined, based on the fact that the
> definition of what constitutes an "access" to a volatile quantity
> is implementation defined.

Now we get into the issue of the meaning of "volatile" itself, and that,
of course, is a whole different discussion.

And I'll certainly agree that that part is totally implementation-defined,
so you can choose to access the value however many times you want.

In that sense

	volatile int p, q;

	p = q = 0;

can, in fact, mean pretty much anything at all. My personal opinion is
that it should be consistent with the other cases, and _not_ load anything
from q, and only emit store instructions.

But clearly, the ill-defined nature of "volatile" itself makes any real
argument on language definitions impossible. A language lawyer can make
almost anything be acceptable.

So instead of trying to argue the meaning of "volatile", I've tried to
show that the C++ language specifications support _not_ loading quite
naturally, with the normal "intuitive" meaning for "volatile".

(And as "volatile" doesn't have much better meaning than the intuitive
and historical one, there's not much else you can go on, I think).

> >	This is not meant as a
> > 	"proof", but it _is_ clearly an indication that other parts of gcc
> > 	(and most programmers) certainly think that the lvalue->rvalue
> > 	conversion always happens, whether the rvalue is used or not.
>
> That g++ currently generates an extra load from "p = 0;" is simply an
> indication that no one has touched the volatile loading code in ages;
> probably since before c++ standardized the result of operator= being
> an lvalue.  It is most definitely not a consious decision.

You misunderstand.

A plain "p = 0;" assignment does _not_ load anything from memory, and I
fully support that. In fact, I would consider it a bug if it did, as it
would make "volatile" completely unusable for IO instructions in C++.

So gcc acts quite normally in this respect, both in C and C++.

My argument is a consistency argument, where one of the corner stones is
exactly the fact that _because_ "p = 0" does not load from memory, then "q
= p = 0" should _also_ not load.

So I'm asking for _consistency_, nothing more.

I think it would also be consistent (but stupid ;) to have "p = 0" do a
load from "p" after the store. I do not think the C++ standard really
implies that in any way, but I'm just saying that it would be consistent
to have the behaviour of

	p = 0; 	// store 0 to 'p', load 'p'
	q = p = 0; // store 0 to 'p', load 'p', store loaded value into 'q', load 'q'

but in this case it's an internal self-consistency that I think is silly;)

Which is why I'd much rather have the consistency of not loading.

I'm also claiming that the C++ standard does _not_ require the
"lvalue->rvalue" conversion to be a dereference, but does, in fact, quite
clearly allow it to be just the value assigned. So the _consistent_
behaviour is, in fact, in no way against the spirit _or_ the letter of the
C++ standard.

(Also note that whether the lvalue->rvalue conversion is always done or
not is not actually something I personally care about. The conversion only
becomes an issue for the argument _if_ you accept that dereferencing is
the only way to do a lvalue->rvalue conversion. Which I do not agree with,
nor do I think the C++ standard claims that to be the case).

		Linus



More information about the Gcc-patches mailing list