为什么Clang 3.6不能为以下程序的a
和b
版本生成相同的程序集?
#include <iostream>
#include <algorithm>
int main(int argc, char** argv)
{
std::cout << std::max(3, argc) << std::endl; // a
//std::cout << std::max({3, argc}) << std::endl; // b
return 0;
}
使用-O3
编译,a
和b
的相关汇编位分别为:
##a
cmpl $2, %edi
movl $3, %esi
cmovgl %edi, %esi
movq __ZNSt3__14coutE@GOTPCREL(%rip), %rdi
##b
movq ___stack_chk_guard@GOTPCREL(%rip), %r15
movq (%r15), %r15
movq %r15, -32(%rbp)
leaq -40(%rbp), %rcx
movl $3, -40(%rbp)
leaq -36(%rbp), %rax
movl %edi, -36(%rbp)
movl $3, %esi
leaq -32(%rbp), %r8
movq %rcx, %rdx
jmp LBB0_1
.align 4, 0x90
LBB0_2:
movl (%rbx), %edi
movq %rax, %rcx
movq %rbx, %rax
LBB0_1:
cmpl %edi, %esi
cmovlq %rax, %rdx
movq %rcx, %rbx
addq $8, %rbx
cmpq %r8, %rbx
movl (%rdx), %esi
jne LBB0_2
movq __ZNSt3__14coutE@GOTPCREL(%rip), %rdi
根据我对汇编的有限了解,看起来版本b
已编译为std::max_element
算法,这明显低于a
中使用的算法的效率。为什么是这样?在使用std::initializer_list
时,我们可以实际期望哪种优化?
答案 0 :(得分:5)
你需要将你的clang升级到更高版本,因为有人显然发现了这种低效率并改进了它:
这是您现在b
示例生成的代码:
movl %edi, %eax
movl $3, (%rsp)
movl %eax, 4(%rsp)
cmpl $3, %eax
cmovlel (%rsp), %eax
它不如原始示例那么整洁,但它比3.6编译器生成的代码更好。
与往常一样,编译器所做的优化在很大程度上取决于作者发现了什么并找到了#34;的解决方案。第一步是#34;让它发挥作用&#34;。然后你看看它更快/更小。
我的铿锵版:
clang version 3.7.0
(http://llvm.org/git/clang.git 490122a3730b4ac7120ba9bee3e5dc51510d68d9)
(http://llvm.org/git/llvm.git 1c63fe6c61b2e1d6050f971f26946cda1e708a9c)