为什么在汇编代码中出现分支,同时比较数字是否在范围内? [英] Why does branching occur in assembly code while comparing for a number to be in range?

查看:177
本文介绍了为什么在汇编代码中出现分支,同时比较数字是否在范围内?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在阅读这个问题,它是被接受的答案。我读了注释,但我无法弄清楚优化产生的原因。



为什么在使用下面的代码时在汇编代码中出现分支?

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆