为什么这个简单的函数的编译器输出如此不同?

时间:2017-09-03 09:07:37

标签: c++ gcc visual-c++ c++14 clang++

我要求C ++编译器生成一个机器编码函数,该函数对const std::vector的元素求和。

#include <vector>

int sum(const std::vector<int>& v)
{
    int s = 0;
    for(const auto e:v) s += e;
    return s;
}

我问编译器x86_64 GCC 7.2带有-O2。它只是说:

sum(std::vector<int, std::allocator<int> > const&):
  mov rdx, QWORD PTR [rdi]
  mov rcx, QWORD PTR [rdi+8]
  xor eax, eax
  cmp rdx, rcx
  je .L4
.L3:
  add eax, DWORD PTR [rdx]
  add rdx, 4
  cmp rdx, rcx
  jne .L3
  rep ret
.L4:
  rep ret

我对编译器Clang 4.0.0提出-O1-O2-O3的问题。好!这是一篇完整的文章。它只是在-O1-O2-O3的文章中操纵了一些形容词。

x86_64 ICC 17与-O2和x86_64 CL 19类似。

然后我回到使用-O3编译器x86_64 GCC 7.2。 x86_64 GCC 7.2现在提供了一个很长的输出。

1 个答案:

答案 0 :(得分:2)

我认为你的问题是:

  

为什么会为这么简单的事情生成如此多的代码?

答案很长但是这样:

当我们操作内存时,现代内存架构可以实现更高的吞吐量......

  • in blocks
  • 并行
  • 关于对给定硬件有效的内存地址边界。

因此,编译器试图通过尽可能地矢量化/并行化操作来优化长向量的情况,同时考虑到存储器架构的特性。

但并非所有向量都是可以作为块有效处理的项目数的倍数。

因此,矢量的开始和结束将通过特定操作单独处理,而(长)矢量的大部分由中间的智能矢量化代码处理。