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