为什么clang用-O0产生低效率的asm(对于这个简单的浮点数总和)?
我正在llvm clang Apple LLVM版本8.0.0(clang-800.0.42.1)上反汇编以下代码:
int main() { float a=0.151234; float b=0.2; float c=a+b; printf("%f", c);}
我没有使用-O规范进行编译,但是我也尝试使用-O0(给出相同的值)和-O2(实际上是计算值并将其存储为预先计算的)
产生的拆卸如下(我删除了不相关的零件)
-> 0x100000f30 <+0>: pushq %rbp 0x100000f31 <+1>: movq %rsp, %rbp 0x100000f34 <+4>: subq $0x10, %rsp 0x100000f38 <+8>: leaq 0x6d(%rip), %rdi 0x100000f3f <+15>: movss 0x5d(%rip), %xmm0 0x100000f47 <+23>: movss 0x59(%rip), %xmm1 0x100000f4f <+31>: movss %xmm1, -0x4(%rbp) 0x100000f54 <+36>: movss %xmm0, -0x8(%rbp) 0x100000f59 <+41>: movss -0x4(%rbp), %xmm0 0x100000f5e <+46>: addss -0x8(%rbp), %xmm0 0x100000f63 <+51>: movss %xmm0, -0xc(%rbp) ...
显然,它正在执行以下操作:
将两个浮点数加载到寄存器xmm0和xmm1
将它们放在堆栈中
从堆栈中将一个值(不是xmm0之前的一个值)加载到xmm0
执行添加。
将结果存储回堆栈。
我发现效率低下是因为:
一切都可以在注册表中完成。我以后不会使用a和b,因此它可以跳过涉及堆栈的任何操作。
即使它想使用堆栈,如果以不同的顺序执行操作,也可以节省从堆栈中重新加载xmm0的时间。
考虑到编译器总是正确的,为什么选择这种策略?
ABOUTYOU
相关分类