Why is the order of evaluation for function parameters unspecified in c++?
Asked Answered
A

2

13

The standard doesn't specify the order of evaluation of arguments with this line:

The order of evaluation of arguments is unspecified.

What does

Better code can be generated in the absence of restrictions on expression evaluation order

imply?

What is the drawback in asking all the compilers to evaluate the function arguments Left to Right for example? What kinds of optimizations do compilers perform because of this unspecified spec?

Apical answered 22/9, 2012 at 3:25 Comment(5)
Allowing the compiler to re-order the evaluation of the operands adds more room for optimization.Roundshouldered
@Mysticial: Absurd as it might look, that should be an answer, and actually the accepted answer!Stoma
What kinds of optimizations do the compilers perform?Apical
If I can think of an example I'll make that an answer.Roundshouldered
Some calling conventions pass parameters right to left. Others pass left to right. It is sometimes more efficient to evaluate in the same order they are pushed.Aricaarick
R
29

Allowing the compiler to re-order the evaluation of the operands adds more room for optimization.

Here's a completely made up example for illustration purposes.

Suppose the processor can:

  • Issue 1 instruction each cycle.
  • Execute an addition in 1 cycle.
  • Execute a multiplication in 3 cycles.
  • Can execute additions and multiplications at the same time.

Now suppose you have a function call as follows:

foo(a += 1, b += 2, c += 3, d *= 10);

If you were to execute this left-to-right on a processor without OOE:

Cycle - Operation
0     -    a += 1
1     -    b += 2
2     -    c += 3
3     -    d *= 10
4     -    d *= 10
5     -    d *= 10

Now if you allow the compiler to re-order them: (and start the multiplication first)

Cycle - Operation
0     -    d *= 10
1     -    a += 1, d *= 10
2     -    b += 2, d *= 10
3     -    c += 3

So 6 cycles vs. 4 cycles.

Again this is completely contrived. Modern processors are much more complicated than that. But you get the idea.

Roundshouldered answered 22/9, 2012 at 3:36 Comment(0)
A
5

Here's a simple example. Suppose you have a function call as follows:

// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);

The compiler needs to dereference p twice (and do some computations based on the result) and call bar once. If the compiler is clever, it might reorder the evaluation to

int temp = *p * 3;
foo(temp, bar(), temp + 1);

That way it has to do the "dereference, multiply by 3" only once. This is known as common subexpression eliminiation.

Aricaarick answered 24/9, 2012 at 15:3 Comment(2)
To be fair, even languages that guarantee order of evaluation can do this, provided they can sort-of prove that the value of p cannot change in between. Of course, with the C memory model that's pretty much impossible to guarantee, which is probably why undefined order of evaluation is necessary to achieve this optimisation.Agar
If it could be proven, the optimizer could reorder the evaluation by the as-if-rule, even if the order is prescribed by the standard.Microgroove

© 2022 - 2024 — McMap. All rights reserved.