In the following code snippet, would compiler do lazy evaluation on condition variables and also do short circuit evaluation?
const bool condition1 = calcCondition1(...);
const bool condition2 = calcCondition2(...);
const bool condition3 = calcCondition3(...);
if (condition1 && condition2 && condition3)
return true;
return false
Such that the actual flow would be something like the following?
if(!calcCondition1(...))
return false;
if(!calcCondition2(...))
return false;
if(!calcCondition3(...))
return false;
return true;
Thank you!
CodePudding user response:
No, unless the compiler figures it up and optimizes it. Note that function bodies from different compilation units (different .cpp
file) are unknown: they are linked into binary after compilation process.
The compiler must assume worst-case scenarios such as calcCondition1
throws an exception or executes exit()
. Or mutate some global state. And in such cases, the semantics must be preserved and everything must be invoked in the written order
That code
bool calcCondition1();
bool calcCondition2();
bool calcCondition3();
bool foo() {
const bool condition1 = calcCondition1();
const bool condition2 = calcCondition2();
const bool condition3 = calcCondition3();
if (condition1 && condition2 && condition3) return true;
return false;
}
and example assembly output:
foo(): # @foo()
push rbp
push rbx
push rax
call calcCondition1()@PLT
mov ebp, eax
call calcCondition2()@PLT
mov ebx, eax
call calcCondition3()@PLT
and bl, bpl
and al, bl
add rsp, 8
pop rbx
pop rbp
ret
Notice that all functions are called one by one
If compiler is sure that it is not a case (I am using a gcc extension):
__attribute__((pure)) bool calcCondition1();
__attribute__((pure)) bool calcCondition2();
__attribute__((pure)) bool calcCondition3();
bool foo() {
const bool condition1 = calcCondition1();
const bool condition2 = calcCondition2();
const bool condition3 = calcCondition3();
if (condition1 && condition2 && condition3) return true;
return false;
}
Then the generated code use the short circuit evaluation
foo(): # @foo()
push rbx
call calcCondition1()@PLT
test al, al
je .LBB0_4
call calcCondition3()@PLT
mov ebx, eax
call calcCondition2()@PLT
test bl, bl
je .LBB0_4
mov ecx, eax
mov al, 1
test cl, cl
je .LBB0_4
pop rbx
ret
.LBB0_4:
xor eax, eax
pop rbx
ret