C++ compiler optimizations and short-circuit evaluation [duplicate]
Asked Answered
H

2

8

Here is my code :

b = f() || b;

The function f() has side effect and it must be always executed. Normally, only the right operand can be short-circuited and this code should work. But I am afraid some compilators reverse the two operands, since it's more efficient to short-circuit a function evaluation rather than a simple variable evaluation. I know that g++ -O3 can break some specifications, but I don't know if this code can be affected.

So, is my code risk-free?

I knew Is short-circuiting logical operators mandated? And evaluation order? but my question was about compilers optimizations, I didn't know that they can't break the standards (even if this would be strange).

Hat answered 25/6, 2015 at 14:17 Comment(6)
g++ -O3 does not break specifications. It might break your code, but not the C++ standard.Felid
@KerrekSB Ok, so it can only break wrong code which worked only by luck with other options ?Townshend
Yes, that's the case in the vast majority of times.Felid
@KerrekSB And what can be the other cases ?Townshend
I don't really know. Sometimes real compiler bugs manifest only when you have lots of optimizations on, but those are bugs, not intentional violations. That said, GCC seems to have -Ofast, which says "Disregard strict standards compliance". I think most of this will concern floating point operations.Felid
@KerrekSB I know this is old, but I would like to add that enabling high optimization levels can persuade the compiler to take advantage of UB. If you have made any assumptions in your code about the behavior of something that is UB, your code is liable to break.Gavrah
C
13

But I am afraid some compilators reverse the two operands

These expressions must be evaluated left-to-right. This is covered in the standard about the operators &&, ||, ?, and ,. They specifically mention the order, as well as enforced sequence points.

§5.14.1 (Logical AND)

The && operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

§5.15.1 (Logical OR)

The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.

§5.16.1 (Conditional operator)

Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.

§5.19.1 (Comma operator)

The comma operator groups left-to-right. A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded value expression (Clause 5). Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field. If the value of the right operand is a temporary (12.2), the result is that temporary.

Regarding your concern about optimizations violating this order, no compilers are not allowed to change the order. Compilers must first and foremost (try to) follow the standard. Then they can try to make your code faster. They may not violate the standard just for the sake of performance. That undermines the entire premise of having a standard.

Confect answered 25/6, 2015 at 14:18 Comment(2)
So, what Kerrek SB means with "It might break your code" ? It can only break wrong code which worked only by luck with other options ?Townshend
I'm not sure what they meant with that comment, they'd have to elaborate.Confect
C
6

It's explicitly stated by the standard that optimized code should behave "as-if" it was exactly the code that was written, as long as you only rely on standard behavior.

Since the standard requires the boolean statements to be evaluated from left to right, no (compliant) optimization can change the order of evaluation.

Conyers answered 25/6, 2015 at 14:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.