为什么在汇编代码中出现分支,同时比较数字是否在范围内? [英] Why does branching occur in assembly code while comparing for a number to be in range?
问题描述
我在阅读这个问题,它是被接受的答案。我读了注释,但我无法弄清楚优化产生的原因。
为什么在使用下面的代码时在汇编代码中出现分支?
x> = start&& x <= end
编辑:
为了清楚起见,理解由接受的答案产生的优化的原因。根据我的理解是编译器生成的汇编代码中的分支。我想知道为什么在生成的代码中有一个分支。
注意,链接的问题有一个根本不同的表达式
x> = start&& x ++< = end
这是根本不同的,因为这里的第二个子表达式有副作用。
请注意,&&&
是一个 short-circuitper operator 。这意味着如果 x> = start
计算为 false
,机器可以更准确地说,当编译器发出<$ c $ <$ p $ <$ p <$ p <$>的指令时, x <= end
c> x> = start&& x <= 时, 可以发出指令以分支 x <= end
c> x> = start 计算为false。
然而,我强调使用在上面的语句中。这是因为 x <= end
没有副作用,因此无论编译器是否分析其评估,都没有关系。
但是,在第二个表达式有副作用的情况下,编译器必须分支。由于&&
是一个短路运算符,在 a&& b ,如果
b
有任何副作用,则 a
计算为
false
;这是在C和大多数(如果不是所有类C语言)短路的要求。
因此,特别是当你看看
define POINT_IN_RANGE_AND_INCREMENT(p,range)
(p <= range.end& p ++> = range.start )
请注意第二个表达式 p ++> = range.start
有副作用。也就是说,(post)通过
1
增加 p
。但是,只有 p <= range.end
计算为 true
,才能观察到副作用。因此,如果 p <= range.end,则编译器必须分支
p ++> = range.start
这导致分支的原因是因为对于机器来评估该表达式,它使用事实如果 p <= range.end
计算为 false
,那么它会自动知道整个表达式计算到 false
,因此它不应评估 p ++> = range.start
有副作用。因此,它必须分支到表达式的第二部分。所以在程序集中:
Ltmp1301:
ldr r1,[sp,#172] @ 4-byte Reload
ldr r1,[r1]
cmp r0,r1
bls LBB44_32
mov r6,r0 @如果比较的结果为假
b LBB44_33 @ branch over第二个表达式
@以避免p ++的副作用
LBB44_32:
ldr r1,[sp,#188] @ 4字节重载
添加r6,r0,#1
Ltmp1302:
ldr r1,[r1]
cmp r0,r1
bhs LBB44_36
$ b b
深深感谢 Oli Charlesworth 提供有见地的评论。
I was reading this question and it's accepted answer. I read the comments but I couldn't figure out the reason for the optimization produced.
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 of optimization produced by the accepted answer. That as I understand is the branching present in the assembly code produced by the compiler. I want to understand why is there a branch in the produced code.
Note that the linked question has a fundamentally different expression
x >= start && x++ <= end
It is fundamentally different because the second sub-expression here has a side effect. I'll explain.
Note that &&
is a short-circuit operator. This means that if x >= start
evaluates to false
, the machine can branch over evaluation of x <= end
.
More precisely, when the compiler emits instructions for x >= start && x <= end
, it can emit instructions to branch over x <= end
when x >= start
evaluates to false.
However, I stress the use of the word can in the above statements. The reason for this is because x <= end
has no side-effects and therefore it doesn't matter if the compiler branches over evaluation of it or not.
But, in the case that the second expression does have side effects the compiler must branch over it. Since &&
is a short-circuit operator, in a && b
, if b
has any side effects they must not be observed if a
evaluates to false
; this is a requirement of short-circuiting in C and most (if not all C-like languages).
So, in particular, when you look at
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-)incrementing p
by 1
. But that side effect can only be observed if p <= range.end
evaluates to true
. Thus, the compiler must branch over evaluation of p++ >= range.start
if p <= range.end
evaluates to false.
The reason this results in a branch is because for machine to evaluate that expression, it uses the fact that if p <= range.end
evaluates to false
, then it automatically knows the entire expression evaluates to false
and therefore it should not evaluate p++ >= range.start
because it has a side-effect. Thus, it must branch over evaluating 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
Deep indebtedness to Oli Charlesworth for insightful comments.
这篇关于为什么在汇编代码中出现分支,同时比较数字是否在范围内?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!