llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.85k stars 11.47k forks source link

Missed optimization for value-init of variable-sized allocation #36699

Open 0775a785-4f8d-448e-9da0-14f81adf2169 opened 6 years ago

0775a785-4f8d-448e-9da0-14f81adf2169 commented 6 years ago
Bugzilla Link 37351
Version trunk
OS Linux
CC @DougGregor,@redbeard0531

Extended Description

https://godbolt.org/g/6yZEKf (compiled with -O3)

char* variableSize(long n) { auto p = new char[n](); for (int i = 0; i < n; i++) { p[i] = 0xff; } return p; }

char* small() { return variableSize(8); }

char* large() { return variableSize(10'000); }

The variableSize() case generates two calls two memset with the second being conditional on n > 0:

variableSize(long): # @​variableSize(long) push r14 push rbx push rax mov rbx, rdi call operator new[](unsigned long) mov r14, rax xor esi, esi mov rdi, rax mov rdx, rbx call memset test rbx, rbx jle .LBB0_2 mov esi, 255 mov rdi, r14 mov rdx, rbx call memset .LBB0_2: mov rax, r14 add rsp, 8 pop rbx pop r14 ret

Note that when clang can see the allocation size it does elide the initial memset:

small(): # @​small() push rax mov edi, 8 call operator new[](unsigned long) mov qword ptr [rax], -1 pop rcx ret large(): # @​large() push rbx mov edi, 10000 call operator new[](unsigned long) mov rbx, rax mov esi, 255 mov edx, 10000 mov rdi, rax call memset mov rax, rbx pop rbx ret

0775a785-4f8d-448e-9da0-14f81adf2169 commented 6 years ago

MSVC and ICC both also handle this poorly: https://godbolt.org/g/i4wMYa

https://developercommunity.visualstudio.com/content/problem/246786/poor-codegen-for-value-init-followed-by-explicit-i.html

0775a785-4f8d-448e-9da0-14f81adf2169 commented 6 years ago

Related g++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85680