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
