为什么Clang能够优化远离std :: initializer_list?

时间:2015-09-03 08:24:24

标签: c++ c++11 optimization

为什么Clang 3.6不能为以下程序的ab版本生成相同的程序集?

#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编译,ab的相关汇编位分别为:

##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时,我们可以实际期望哪种优化?

1 个答案:

答案 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)