Home > OS >  Lazy Evaluation on condition variables
Lazy Evaluation on condition variables

Time:09-23

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
  • Related