为啥 gcc 会产生这个奇怪的程序集 vs clang?
Posted
技术标签:
【中文标题】为啥 gcc 会产生这个奇怪的程序集 vs clang?【英文标题】:Why does gcc produce this weird assembly vs clang?为什么 gcc 会产生这个奇怪的程序集 vs clang? 【发布时间】:2020-02-16 02:05:46 【问题描述】:我试图弄清楚 gcc 和 clang 之间的区别以及它们如何处理std::vector
。有更多知识的人能解释一下为什么 gcc 和 clang 会产生如此不同的输出吗?
gcc 9.2:https://godbolt.org/z/AFN46d 铿锵声9.0:https://godbolt.org/z/kEkpWE
程序:
#include <vector>
int foo(int a)
auto vec = std::vector<int>;
vec.push_back(1);
vec.push_back(2);
return vec[1] * a;
int main ()
return foo(5) + foo(4);
clang 生成非常易于理解的程序集。然而,gcc 会产生这种奇怪的东西:
void std::vector<int, std::allocator<int> >::_M_realloc_insert<int>(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int&&):
movabs rcx, 2305843009213693951
push r15
push r14
push r13
push r12
push rbp
push rbx
sub rsp, 24
mov r12, QWORD PTR [rdi+8]
mov r8, QWORD PTR [rdi]
mov rax, r12
sub rax, r8
sar rax, 2
cmp rax, rcx
je .L16
mov r15, rdx
mov rdx, rsi
mov rbp, rdi
mov r13, rsi
sub rdx, r8
test rax, rax
je .L11
movabs r14, 9223372036854775804
lea rsi, [rax+rax]
cmp rax, rsi
jbe .L17
这些神奇的数字是从哪里来的?
【问题讨论】:
我想知道为什么他们都没有优化到return 2 * a;
foo(int)
的代码由foo(int):
行引入,您引用了向量证明成员函数的程序集
@M.M 我想这是因为::operator new
可能会在另一个翻译单元中被替换。
@L.F.即使存在全局替换,它也被允许优化,因为 C++14,see here
【参考方案1】:
GCC 尽量保证安全并发出一些额外的检查。您看到的第一个常量仅仅是
__gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(int)
并且构成 x86-64 上整数向量的最大可能大小。
第二个常数似乎只是
__gnu_cxx::__numeric_traits<ptrdiff_t>::__max
四舍五入以被sizeof(int)
整除。
一般来说,这些东西来自 libstdc++ 中的各种max_size()
方法。 clang 有可能证明一些检查是不必要的。
【讨论】:
以上是关于为啥 gcc 会产生这个奇怪的程序集 vs clang?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 GCC 会为几乎相同的 C 代码生成如此完全不同的程序集?