对于此简单功能,为什么编译器输出如此不同

Why are compiler outputs so different for this simple function?

本文关键字:输出 编译器 为什么 于此 简单 功能      更新时间:2023-10-16

我要求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;
}

我用-O2询问编译器X86_64 GCC 7.2。它只是说:

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

我对-O1-O2-O3的编译器Clang 4.0.0提出了同样的要求。出色地!那是一篇完整的文章。它只是操纵他在-O1-O2-O3的文章中的一些形容词。

类似的情况与X86_64 ICC 17一起使用-O2,X86_64 Cl 19。

我返回使用-O3的编译器X86_64 GCC 7.2。X86_64 GCC 7.2现在提供冗长的输出。

我认为您的问题是:

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

答案很长,但会像这样:

当我们操纵内存时,现代记忆体系结构实现了更多的吞吐量...

  • 在块中
  • 并行
  • 在给定硬件有效的内存地址边界上。

因此,编译器试图通过考虑内存体系结构的特征来尽可能通过向量/平行操作来优化长向量的情况。

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

因此,向量的开始和结尾分别处理特定的操作,而a(长)向量的大部分是由中间的巧妙矢量代码处理的。