Why does branching occur in the assembly code when comparing a number in range?

I read this question and it accepted the answer. I read the comments, but I could not understand the reason for the optimization created.

Why does branching occur in assembly code when using the following code?

x >= start && x <= end 

EDIT:
For clarity, I want to understand the reason for the optimization created by the accepted answer. This, as I understand it, is a branch present in the assembly code created by the compiler. I want to understand why there is a branch in the generated code.

+6
source share
1 answer

Please note that the related question has a fundamentally different expression

 x >= start && x++ <= end 

This is fundamentally different because the second subexpression here has a side effect. I will explain.

Note that && is a short circuit operator . This means that if x >= start evaluates to false , the machine can go through the evaluation x <= end .

More precisely, when the compiler issues instructions for x >= start && x <= end , it can issue instructions to jump to x <= end when x >= start gets false.

However, I emphasize the use of the word can in the above statements. The reason for this is that x <= end has no side effects, and therefore it doesn’t matter if the compiler branches over its evaluation or not.

But in the event that the second expression has side effects, the compiler must expand it. Since && is a short circuit operator, in a && b , if b has any side effects, they should not be observed if a is evaluated to false ; this is a short circuit requirement in C and most (if not all C-like languages).

So, in particular, when you look

 define POINT_IN_RANGE_AND_INCREMENT(p, range) (p <= range.end && p++ >= range.start) 

note that the second expression p++ >= range.start has a side effect. Namely, (post), increasing p by 1 . But this side effect can only be observed if p <= range.end evaluates to true . Thus, the compiler must pass a score of p++ >= range.start if p <= range.end is false.

The reason this leads to the branch is because in order for the machine to evaluate this expression, it uses the fact that if p <= range.end evaluates to false , then it automatically knows that the whole expression evaluates as false , and therefore it should not evaluate p++ >= range.start because it has a side effect. Thus, it should branch out over the evaluation of the second part of the expression. So in the assembly:

 Ltmp1301: ldr r1, [sp, #172] @ 4-byte Reload ldr r1, [r1] cmp r0, r1 bls LBB44_32 mov r6, r0 @ if the result of the compare is false b LBB44_33 @ branch over evaluating the second expression @ to avoid the side effects of p++ LBB44_32: ldr r1, [sp, #188] @ 4-byte Reload adds r6, r0, #1 Ltmp1302: ldr r1, [r1] cmp r0, r1 bhs LBB44_36 

Oli Charlesworth deep indebtedness for insightful comments.

+10
source

Source: https://habr.com/ru/post/947327/


All Articles