【发布时间】:2019-10-18 21:15:15
【问题描述】:
我很好奇为什么下面这段代码:
#include <string>
int main()
{
std::string a = "ABCDEFGHIJKLMNO";
}
使用-O3 编译时会产生以下代码:
main: # @main
xor eax, eax
ret
(我完全理解不需要未使用的a,因此编译器可以从生成的代码中完全省略它)
但是下面的程序:
#include <string>
int main()
{
std::string a = "ABCDEFGHIJKLMNOP"; // <-- !!! One Extra P
}
产量:
main: # @main
push rbx
sub rsp, 48
lea rbx, [rsp + 32]
mov qword ptr [rsp + 16], rbx
mov qword ptr [rsp + 8], 16
lea rdi, [rsp + 16]
lea rsi, [rsp + 8]
xor edx, edx
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long)
mov qword ptr [rsp + 16], rax
mov rcx, qword ptr [rsp + 8]
mov qword ptr [rsp + 32], rcx
movups xmm0, xmmword ptr [rip + .L.str]
movups xmmword ptr [rax], xmm0
mov qword ptr [rsp + 24], rcx
mov rax, qword ptr [rsp + 16]
mov byte ptr [rax + rcx], 0
mov rdi, qword ptr [rsp + 16]
cmp rdi, rbx
je .LBB0_3
call operator delete(void*)
.LBB0_3:
xor eax, eax
add rsp, 48
pop rbx
ret
mov rdi, rax
call _Unwind_Resume
.L.str:
.asciz "ABCDEFGHIJKLMNOP"
当使用相同的-O3 编译时。我不明白为什么它不能识别 a 仍然未使用,不管字符串长了一个字节。
这个问题与 gcc 9.1 和 clang 8.0 相关,(在线:https://gcc.godbolt.org/z/p1Z8Ns)因为我观察到的其他编译器要么完全删除未使用的变量 (ellcc),要么为其生成代码,而不管字符串的长度。
【问题讨论】:
-
可能链接到一些short string optimization practices ?
-
会不会是小字符串优化的原因?尝试将
a声明为 volatile,您会看到这两个字符串的处理方式不同。最长的似乎分配在堆上。 gcc.godbolt.org/z/WUuJIB -
参见this thread 讨论是否允许编译器优化动态分配
-
我改用
string_view,它仍然会优化更长的字符串:godbolt.org/z/AAViry -
尝试附加
-stdlib=libc++以使用 Clang 进行编译 ;-)
标签: c++ gcc compilation clang compiler-optimization