https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85680
Bug ID: 85680 Summary: Missed optimization for value-init of variable-sized allocation Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redbeard0531 at gmail dot com Target Milestone: --- 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 both being conditional on n > 0 if I'm reading this right), but the two checks are done in different ways. That may be a second optimizer bug that it missed a jump-threading opportunity. variableSize(long): push rbx mov rbx, rdi call operator new[](unsigned long) mov rcx, rax mov rax, rbx sub rax, 1 js .L5 lea rax, [rbx-2] mov edx, 1 mov rdi, rcx cmp rax, -1 cmovge rdx, rbx xor esi, esi call memset mov rcx, rax .L5: test rbx, rbx jle .L1 mov rdi, rcx mov rdx, rbx mov esi, 255 call memset mov rcx, rax .L1: mov rax, rcx pop rbx ret Note that when g++ 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 Related clang bug: https://bugs.llvm.org/show_bug.cgi?id=37351