Re: C++ order of evaluation of operands, arguments

2015-11-29 Thread Jason Merrill

On 11/25/2015 01:25 PM, Martin Sebor wrote:

On 11/24/2015 02:55 AM, Andrew Haley wrote:

On 23/11/15 23:01, Jason Merrill wrote:

There's a proposal working through the C++ committee to define the order
of evaluation of subexpressions that previously had unspecified
ordering:

http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf

I agree with much of this, but was concerned about the proposal to
define order of evaluation of function arguments as left-to-right, since
GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.

Any thoughts?


Not about PUSH_ARGS_REVERSED targets, but my two-penn'orth:

The proposal seems to be a bit of a minefield.  This one:

a(b, c, d)

is a bit counter-intuitive.  I wouldn't expect a to be evaluated before
the arg list.  I wonder how many C++ programmers would.


The motivating example in the paper suggests that many C++
programmers expect a left to right order of evaluation here
due to the commonality of constructs like chains of calls.


Yes, although chains of calls like

  var.fn1(args1).fn2(args2)

are covered by the "a.b" bullet.  The above bullet would be more 
relevant to a chain like


  fn1(args1)(args2)

or

  [captures]{...}(args)

Jason



Re: C++ order of evaluation of operands, arguments

2015-11-26 Thread Michael Matz
Hi,

On Thu, 26 Nov 2015, David Brown wrote:

> That is all true - but if you have to pick an order that makes sense to 
> users, especially of functions that are not varargs (i.e., most 
> functions), then left-to-right is the only logical, natural order - at 
> least for those of use who use left-to-right languages.

Exactly, what's feeling humanly natural here is cultural (and I'd argue 
there's a fairly large percentage of the population who are neither ltr 
not rtl, but rather top-to-bottom), and therefore ...

> really going to be a big issue?  One should not limit the language just 
> because of a tiny efficiency issue with rarely-used cases.

... this is the only objectively measurable dimension, and hence _that_ is 
exactly how the language should be limited in such cases, if it must be 
limited at all (which seems indeed a bit dubious after 30 years as the 
proposal mentions itself) [1].


Ciao,
Michael.

[1] I'm trying (but failing) to not even start the argument that if the 
goal is to make C++ "make more sense to users" that this already failed in 
'98, got worse with later revisions, and fixating evaluation order is 
helping just so slightly (if at all), that it all seems a bit ridiculous 
to me.


Re: C++ order of evaluation of operands, arguments

2015-11-26 Thread David Brown
On 25/11/15 15:47, Michael Matz wrote:
> Hi,
> 
> On Tue, 24 Nov 2015, Richard Biener wrote:
> 
>> On Tue, Nov 24, 2015 at 12:01 AM, Jason Merrill  wrote:
>>> There's a proposal working through the C++ committee to define the order of
>>> evaluation of subexpressions that previously had unspecified ordering:
>>>
>>> http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
>>>
>>> I agree with much of this, but was concerned about the proposal to define
>>> order of evaluation of function arguments as left-to-right, since GCC does
>>> right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.
> 
> Actually the most natural order for an (normal, stack-passing) 
> implementation that supports varargs is right-to-left, so the proposal has 
> it exactly backwards.  (Reason being that named arguments then have 
> constant offsets from stack pointer).
> 
> right-to-left is also the better order for all ABIs that pass (at least 
> some) arguments on stack but give left arguments smaller offsets from 
> top-of-stack (as most ABIs do).
> 

That is all true - but if you have to pick an order that makes sense to
users, especially of functions that are not varargs (i.e., most
functions), then left-to-right is the only logical, natural order - at
least for those of use who use left-to-right languages.

How often would left-to-right evaluation actually cause efficiency
problems?  It would only be for functions that take a lot of parameters
or a variable number of parameters, and then only when calling them with
arguments that are calculated in a way that might have side-effects
(otherwise the compiler is free to re-order them anyway).  Is that
really going to be a big issue?  One should not limit the language just
because of a tiny efficiency issue with rarely-used cases.


(The other orderings discussed in the proposal seem fair enough - it is
only function parameter ordering that is an issue, I think.)






Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Martin Sebor

On 11/25/2015 11:49 AM, Andrew Haley wrote:

On 11/25/2015 06:25 PM, Martin Sebor wrote:

The motivating example in the paper suggests that many C++
programmers expect a left to right order of evaluation here
due to the commonality of constructs like chains of calls.


Sure, I often see

   foo.bar(1).bar(2).bar(3), etc.

but does anyone actually do

   foo(1)bar(2)bar(3)  ?


That doesn't look syntactically valid to me but I suspect what
you mean might be closer to something like this:

foo(1)(bar(2))(baz(3))

which with the right declarations is just a shorthand for this:

   foo(1).operator()(bar(2)).operator()(bar(3));

Having foo(1) evaluate before bar(2) becomes important when
(if) one of the uniform call syntax proposals is adopted. With
that, it will possible to write the expression above like so:

  operator()(operator()(foo(1), bar(2)), bar(3));

or more generally for (almost) any member function F:

  F (F (foo (1), bar (2)), bar (3));

If C++ were to guarantee an order in which function arguments
were evaluated without also imposing an order on the operand
of the function call expression, uniform calls would be error
prone to use.

Martin



Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Jonathan Wakely
On 25 November 2015 at 19:38,   wrote:
> I'm really wondering about this proposal.  It seems that it could affect 
> optimization.  It also seems to be a precedent that may not be a good one to 
> set.  Consider the dozen or so "undefined behavior" examples in 
> https://pdos.csail.mit.edu/papers/ub:apsys12.pdf -- would the committee want 
> to remove ALL of those?

No.

I'm not aware of any suggestion to remove ANY of those.


Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Paul_Koning

> On Nov 25, 2015, at 1:25 PM, Martin Sebor  wrote:
> 
> On 11/24/2015 02:55 AM, Andrew Haley wrote:
>> On 23/11/15 23:01, Jason Merrill wrote:
>>> There's a proposal working through the C++ committee to define the order
>>> of evaluation of subexpressions that previously had unspecified ordering:
>>> 
>>> http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
>>> 
>>> I agree with much of this, but was concerned about the proposal to
>>> define order of evaluation of function arguments as left-to-right, since
>>> GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.
>>> 
>>> Any thoughts?
>> 
>> Not about PUSH_ARGS_REVERSED targets, but my two-penn'orth:
>> 
>> The proposal seems to be a bit of a minefield.  This one:
>> 
>> a(b, c, d)
>> 
>> is a bit counter-intuitive.  I wouldn't expect a to be evaluated before
>> the arg list.  I wonder how many C++ programmers would.
> 
> The motivating example in the paper suggests that many C++
> programmers expect a left to right order of evaluation here
> due to the commonality of constructs like chains of calls.
> 
> Incidentally, both GCC and Clang evaluate the first operand
> of the function call expression first in C as well in C++
> (the program below prints a b c d when compiled with GCC,
> and a d c b with Clang).
> 
> Interestingly, though, not all compilers take that approach.
> IBM XLC, for example, evaluates it last (and the program below
> prints b c d a).

I thought the order depends on target architecture, because of the argument 
passing rules.  I distinctly remember seeing right to left on x86 (because they 
are pushed on the stack, leftmost argument on top) and left to right on MIPS 
(because they go into registers, at least the first 4 or 8 arguments).

I'm really wondering about this proposal.  It seems that it could affect 
optimization.  It also seems to be a precedent that may not be a good one to 
set.  Consider the dozen or so "undefined behavior" examples in 
https://pdos.csail.mit.edu/papers/ub:apsys12.pdf -- would the committee want to 
remove ALL of those?  If yes, what will that do to performance?  If no, what 
are the criteria by which to decide yes or no for each individual example?  And 
I assume there are probably more "things the beginning programmer wouldn't 
expect" issues in C and C++.

paul


Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Andrew Haley
On 11/25/2015 06:25 PM, Martin Sebor wrote:
> The motivating example in the paper suggests that many C++
> programmers expect a left to right order of evaluation here
> due to the commonality of constructs like chains of calls.

Sure, I often see

  foo.bar(1).bar(2).bar(3), etc.

but does anyone actually do

  foo(1)bar(2)bar(3)  ?

That's what I'm talking about.

Andrew.



Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Martin Sebor

On 11/24/2015 02:55 AM, Andrew Haley wrote:

On 23/11/15 23:01, Jason Merrill wrote:

There's a proposal working through the C++ committee to define the order
of evaluation of subexpressions that previously had unspecified ordering:

http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf

I agree with much of this, but was concerned about the proposal to
define order of evaluation of function arguments as left-to-right, since
GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.

Any thoughts?


Not about PUSH_ARGS_REVERSED targets, but my two-penn'orth:

The proposal seems to be a bit of a minefield.  This one:

a(b, c, d)

is a bit counter-intuitive.  I wouldn't expect a to be evaluated before
the arg list.  I wonder how many C++ programmers would.


The motivating example in the paper suggests that many C++
programmers expect a left to right order of evaluation here
due to the commonality of constructs like chains of calls.

Incidentally, both GCC and Clang evaluate the first operand
of the function call expression first in C as well in C++
(the program below prints a b c d when compiled with GCC,
and a d c b with Clang).

Interestingly, though, not all compilers take that approach.
IBM XLC, for example, evaluates it last (and the program below
prints b c d a).

  extern int printf (const char*, ...);

  void f (int b, int c, int d) { }

  typedef void F (int, int, int);

  F* f1 (void) { printf ("a\n"); return f; }
  int f2 (void) { printf ("b\n"); return 0; }
  int f3 (void) { printf ("c\n"); return 0; }
  int f4 (void) { printf ("d\n"); return 0; }

  int main ()
  {
  #define a f1()
  #define b f2()
  #define c f3()
  #define d f4()

a (b, c, d);
}

Martin


Re: C++ order of evaluation of operands, arguments

2015-11-25 Thread Michael Matz
Hi,

On Tue, 24 Nov 2015, Richard Biener wrote:

> On Tue, Nov 24, 2015 at 12:01 AM, Jason Merrill  wrote:
> > There's a proposal working through the C++ committee to define the order of
> > evaluation of subexpressions that previously had unspecified ordering:
> >
> > http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
> >
> > I agree with much of this, but was concerned about the proposal to define
> > order of evaluation of function arguments as left-to-right, since GCC does
> > right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.

Actually the most natural order for an (normal, stack-passing) 
implementation that supports varargs is right-to-left, so the proposal has 
it exactly backwards.  (Reason being that named arguments then have 
constant offsets from stack pointer).

right-to-left is also the better order for all ABIs that pass (at least 
some) arguments on stack but give left arguments smaller offsets from 
top-of-stack (as most ABIs do).

> The reason we have PUSH_ARGS_REVERSED is to get more optimal
> code generation for calls reducing lifetime of argument computation
> results.  Like when you have
> 
>  foo (bar(), baz())
> 
> then generate
> 
>   reg = bar();
>   push reg;
>   reg = baz();
>   push reg;
>   foo ();
> 
> instead of
> 
>   reg = baz();
>   spill reg;
>   reg = bar();
>   push reg;
>   push spilled reg;
>   foo ();

Your examples are switched, but the idea is the correct one (result of bar 
needs to be pushed last in the x86 ABI).

> I would like to get rid of PUSH_ARGS_REVERSED (as used in 
> gimplification) because it's also one source of very early IL 
> differences across archs.

Actually most other targets should also act as if PUSH_ARGS_REVERSED, not 
only x86_64.


Ciao,
Michael.


Re: C++ order of evaluation of operands, arguments

2015-11-24 Thread Martin Sebor

On 11/23/2015 04:01 PM, Jason Merrill wrote:

There's a proposal working through the C++ committee to define the order
of evaluation of subexpressions that previously had unspecified ordering:

http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf

I agree with much of this, but was concerned about the proposal to
define order of evaluation of function arguments as left-to-right, since
GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.

Any thoughts?


I have no comments on the impact on the implementation but I do
have a couple of general concerns with the proposal.

As others have already suggested, I think a change like this needs
to be coordinated with WG14 and made either in both languages or
in neither.  If C++ were to make it alone, C++ programmers who only
occasionally write C code would be prone to introducing bugs into
their C code by relying on the C++ guarantees.  As WG14 is just
starting to talk about the goals for C2x, this seems like a good
time to bring it up for consideration.

Even in C++, though, I'd worry that specifying the evaluation order
for just a subset of expression would lead to portability bugs
creeping in as programmers inadvertently start to assume that
the same order is guaranteed for all expressions.

Martin


Re: C++ order of evaluation of operands, arguments

2015-11-24 Thread Eric Botcazou
> In addition, I don't see anything about C compatibility here.  It
> would be very confusing, to say the least, if this were to be defined
> in C++ but not C.

Or at least they should get some form of guarantee that future C standards 
will not introduce incompatible rules.

-- 
Eric Botcazou


Re: C++ order of evaluation of operands, arguments

2015-11-24 Thread Andrew Haley
On 23/11/15 23:01, Jason Merrill wrote:
> There's a proposal working through the C++ committee to define the order 
> of evaluation of subexpressions that previously had unspecified ordering:
> 
> http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
> 
> I agree with much of this, but was concerned about the proposal to 
> define order of evaluation of function arguments as left-to-right, since 
> GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.
> 
> Any thoughts?

Not about PUSH_ARGS_REVERSED targets, but my two-penn'orth:

The proposal seems to be a bit of a minefield.  This one:

a(b, c, d)

is a bit counter-intuitive.  I wouldn't expect a to be evaluated before
the arg list.  I wonder how many C++ programmers would.

In addition, I don't see anything about C compatibility here.  It
would be very confusing, to say the least, if this were to be defined
in C++ but not C.

Andrew.


Re: C++ order of evaluation of operands, arguments

2015-11-24 Thread Richard Biener
On Tue, Nov 24, 2015 at 12:01 AM, Jason Merrill  wrote:
> There's a proposal working through the C++ committee to define the order of
> evaluation of subexpressions that previously had unspecified ordering:
>
> http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf
>
> I agree with much of this, but was concerned about the proposal to define
> order of evaluation of function arguments as left-to-right, since GCC does
> right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.
>
> Any thoughts?

The reason we have PUSH_ARGS_REVERSED is to get more optimal
code generation for calls reducing lifetime of argument computation
results.  Like when you have

 foo (bar(), baz())

then generate

  reg = bar();
  push reg;
  reg = baz();
  push reg;
  foo ();

instead of

  reg = baz();
  spill reg;
  reg = bar();
  push reg;
  push spilled reg;
  foo ();

where GCC cannot re-order baz() and bar() later because the undefined evaluation
order isn't exposed in the IL.

Of course this matters most to archs that pass arguments via the stack.  And it
doesn't work in the case above because we don't interleave argument setup
of foo () with the calls.

I would like to get rid of PUSH_ARGS_REVERSED (as used in gimplification)
because it's also one source of very early IL differences across archs.

But because of the above idea the effects on code generation may be visible.

As x86_64 is affected investigating the effects on it (and i?86 for the stack
passing case) would be a start.

Of course in the end the frontend should be responsible for enforcing proper
evaluation order of side-effects in arguments so PUSH_ARGS_REVERSED
might still do all the important parts of getting better argument
setup for calls.

Richard.

> Jason


C++ order of evaluation of operands, arguments

2015-11-23 Thread Jason Merrill
There's a proposal working through the C++ committee to define the order 
of evaluation of subexpressions that previously had unspecified ordering:


http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2015/p0145r0.pdf

I agree with much of this, but was concerned about the proposal to 
define order of evaluation of function arguments as left-to-right, since 
GCC does right-to-left on PUSH_ARGS_REVERSED targets, including x86_64.


Any thoughts?

Jason