janjust
janjust

Reputation: 816

Speculative conditional execution C/C++

So I had a discussion with a colleague at work regarding the order of evaluation execution. Consider this conditional:

if (a > b && ref++) { do something }

We both agree that as per C standard the order is from left to right. However, the disagreement is that despite the order of evaluation, some instructions whose data will eventually be evaluated may be speculatively executed and then remain in this state despite the lazy evaluation.

For instance, ref is incremented before evaluating a > b, and the evaluation still happens left to right, that is the actual jump greater than instruction for both a > b and rev > 0 are executed in-order left to right, and abandoned at the first instance when !true. Now this goes against the whole concept of lazy evaluation, but what if ref is a stream of instructions, an inlined function maybe. It would make more sense to start executing some instructions speculatively. The concern is: are those instructions committed, even half way through.

Thoughts?

Upvotes: 6

Views: 678

Answers (3)

Bathsheba
Bathsheba

Reputation: 234715

C compilers are permitted to implement the "as-if" rule, meaning that they can do anything they like so long as the program's intent is respected.

Consider (a > b && ref++). The intention here is that ref will only be incremented if a > b is 1, and that must be the observed behaviour. This is because the right hand argument of && is only evaluated if the left hand argument is 1. However the generated assembly code might be such that the CPU can speculatively increment ref (branch prediction), and retract that incrementation with a pipeline dump if appropriate.

Upvotes: 1

Jean-François Fabre
Jean-François Fabre

Reputation: 140186

It's not possible with a > b && ref++ because of && operator short-circuits.

Think of that case:

f = fopen("foo.txt");
if ((f != NULL) && fread(buffer,10,1,f)) { ...

executing the second part if f==NULL would be a bug because the first part protects against it.

On the contrary, nothing prevents the compiler to do whatever it wants here:

a > b & ref++

& is the arithmetic and so both conditions are always executed. So even if the first condition is false, ref is incremented.

Upvotes: 1

Stephan Lechner
Stephan Lechner

Reputation: 35154

Operator && (as well as operator ||) are special in a sense as they guarantee "short-cut-evaluation" from left to right. This means that for a condition like expr1 && expr2, expr1 will always be evaluated first, and - even more - that expr2 will not get evaluated at all if expr1 already evaluated to false. This is not an optimization, this is guaranteed by the language.

Hence, in if (a > b && ref++), expression ref++ will be evaluated (including it's side effect of incrementing ref) if and only if a > b evaluates to true.

Upvotes: 8

Related Questions