下面是使用clang的compiled代码:
#include <stdint.h>
int f(int32_t a, int32_t b) {
int32_t result;
if (a < 10) {
result = a + b;
} else {
result = a * b;
}
return result;
}
int main() {;
int res = f(5, 9);
if (res > 5) {
return res;
}
return 0;
}
字符串
现在为if (a < 10)
生成的程序集如下所示:
subs w8, w8, #10
cset w8, ge
tbnz w8, #0, .LBB0_2
...
.LBB0_1:
...
add w8, w8, w9
...
.LBB0_2:
...
mul w8, w8, w9
型
我们可以看到,当w8 = 0
时,分支将转到加法块。
当cset
指令不满足条件ge
时,w8
被设置为0
。
当标志N
(负)和V
(溢出)相等时,满足ge
条件。
这两个标志都由最后一个标志设置指令subs
指令设置。
现在我不明白的是,为什么要在cset
指令中使用ge
条件,而不是使用类似pl
条件的东西。为什么我们要额外检查w8
小于min有符号32 int,它如何转换为我们提供的原始高级编译代码?
我意识到我最初的问题并没有完全代表我对这个编译的怀疑,我也完全意识到我没有优化编译,我故意这样做是为了实现下面的编译程序集。
我主要关心的是,如果a
被设置为-2147483643
,现在结果是溢出的,因为它将小于-2^31
,所以它将变成正数,因此负数标志不会被设置,所以我们有一个情况,即N != V
通过高级代码-2147483643
确实小于10
。
2条答案
按热度按时间eqqqjvef1#
您的代码没有优化,因为您没有打开优化。您询问的低效率在启用任何数量的优化后都没有发现(例如
-O3
)。jaxagkaj2#
我没什么经验,但我相信
字符串
意味着如果w8 >= 10后藤LBBO_2
因为当w8大于或等于10时,
subs w8, w8, #10
将标志设置为真