【发布时间】:2015-09-21 09:37:05
【问题描述】:
考虑以下 C++ 代码:
bool foo(int x, int y, int z, int P) {
return (x < P && y > P && z > P);
}
int tryout(int iS, int iP) {
if(foo(iS,iS,iS,iP)) {
printf("%d", 1000);
} else {
printf("%d", 10);
}
return 0;
}
使用 Intel 的 C++ 编译器时,代码会生成以下汇编代码:
L__routine_start__Z3fooiiii_0:
foo(int, int, int, int):
cmpl %ecx, %edi #5.15
jge ..B1.4 # Prob 50% #5.15
cmpl %ecx, %esi #5.24
jle ..B1.4 # Prob 50% #5.24
movl $1, %esi #5.15
xorl %eax, %eax #5.15
cmpl %ecx, %edx #5.15
cmovg %esi, %eax #5.15
ret #5.15
..B1.4: # Preds ..B1.2 ..B1.1
xorl %eax, %eax #5.15
ret #5.15
L__routine_start__Z6tryoutii_1:
tryout(int, int):
pushq %rsi #11.28
cmpl %esi, %edi #5.15
jge ..B2.4 # Prob 50% #5.15
jle ..B2.4 # Prob 50% #5.24
movl $.L_2__STRING.0, %edi #14.8
movl $1000, %esi #14.8
xorl %eax, %eax #14.8
call printf #14.8
jmp ..B2.5 # Prob 100% #14.8
..B2.4: # Preds ..B2.1 ..B2.2
movl $.L_2__STRING.0, %edi #16.5
movl $10, %esi #16.5
xorl %eax, %eax #16.5
call printf #16.5
..B2.5: # Preds ..B2.4 ..B2.3
xorl %eax, %eax #19.10
popq %rcx #19.10
ret #19.10
.L_2__STRING.0:
.byte 37
.byte 100
.byte 0
我有两个问题:
- 为什么在
tryout方法中有两次跳转到..B2.4而只有一个if 语句? -
foo方法中的这段代码有什么作用?movl $1, %esi #5.15 xorl %eax, %eax #5.15 cmpl %ecx, %edx #5.15 cmovg %esi, %eax #5.15
【问题讨论】:
-
这应该是C 还是 C++?
-
您对
foo()的调用将始终返回false,因此您将始终打印10。我想知道编译器是否最初允许这两种情况,然后在优化期间添加了第二个跳转语句调用 printf 10 100% 的时间,因为打印 1000 永远不会发生。 -
@cad: 代码用c++编写,用-O3编译
-
你的表情减少到
iS < iP && iS > iP && iS > iP。由于iS < iP不能为真而iS > iP,结果为0/假。由于这将始终为 0/false,因此无论结果如何,都将始终跳转到..B2.4以打印 10。事实上,cmpl、jge和jle指令甚至不应该存在,因为它是不必要的;它们应替换为jmp ..B2.4。不知道为什么没有发生这种情况...... -
@ChronoKitsune 实际上从
cmpl %esi, %edi到jmp ..B2.5的所有内容都可以删除——无需跳转。该程序实际上是对 printf 的一次调用
标签: c++ optimization assembly x86