Ase*_*sal 6 c c++ math optimization performance
我正在读这个问题,这是接受的答案.我阅读了评论,但我无法弄清楚产生优化的原因.
使用以下代码时,为什么在汇编代码中出现分支?
x >= start && x <= end
Run Code Online (Sandbox Code Playgroud)
编辑:
为清楚起见,我想了解接受答案产生的优化原因.据我所知,编译器生成的汇编代码中存在分支.我想了解为什么生成的代码中有一个分支.
jas*_*son 10
请注意,链接的问题具有根本不同的表达
x >= start && x++ <= end
Run Code Online (Sandbox Code Playgroud)
它根本不同,因为这里的第二个子表达具有副作用.我会解释一下.
注意,这&&是一个短路操作员.这意味着如果x >= start评估为false,则机器可以分支评估x <= end.
更准确地说,当编译器发出指令时x >= start && x <= end,它可以发出指令,x <= end在x >= start计算结果为false 时进行分支.
但是,我强调在上述陈述中使用单词can.这样做的原因是因为x <= end没有副作用,因此编译器是否对其进行分支并不重要.
但是,如果第二个表达式确实有副作用,编译器必须对其进行分支.由于&&是短路操作员,a && b如果b有任何副作用,如果评估,则不得观察a到false; 这是C和大多数(如果不是所有C语言)短路的要求.
所以,特别是当你看的时候
define POINT_IN_RANGE_AND_INCREMENT(p, range)
(p <= range.end && p++ >= range.start)
Run Code Online (Sandbox Code Playgroud)
请注意,第二个表达式p++ >= range.start有副作用.即,(后)递增p通过1.但只有在p <= range.end评估时才能观察到这种副作用true.因此,编译器必须对p++ >= range.startif的p <= range.end计算结果进行分支.
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
Run Code Online (Sandbox Code Playgroud)
Deep indebtedness to Oli Charlesworth for insightful comments.