This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/86276] New: Poor codegen when returning a std::vector
- From: "redbeard0531 at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 22 Jun 2018 01:43:44 +0000
- Subject: [Bug c++/86276] New: Poor codegen when returning a std::vector
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86276
Bug ID: 86276
Summary: Poor codegen when returning a std::vector
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/aCiuAy
While I'm a bit sad that good() isn't just "ret", I think that the current
rules for allocation elision require something like that codegen.
I'd expect bad() to codegen to roughly the same as good(), but then rather than
calling operator delete, it should store [rax, rax + 1, rax + 22] to the three
qwords starting at the out pointer. Instead, it does things like checking if
the vector pointer it just zeroed is still zero to see if it needs to be
deleted. It also seems to register an exception landing pad (I'm guessing to
cover the operator new call) to handle freeing the vector's memory, even though
it should know it isn't holding any.
If I had to guess, I'd say the problem is that it thinks the hidden return out
pointer has escaped when it hasn't really until a successful return. I'm pretty
sure nothing in the language allows any way to access the return value before a
function returns like that, but I'm now really curious if I'm wrong. If there
is, is there any way to tell gcc that I promise I'm not doing anything quite
that stupid?
PS- is it helpful to include the code and asm here in addition to the godbolt
links?
#include <vector>
#include <cstdint>
auto good() {
std::vector<uint8_t> something;
something.reserve(22);
something = {0x02};
//return something; Only difference from bad
}
auto bad() {
std::vector<uint8_t> something;
something.reserve(22);
something = {0x02};
return something;
}
good():
sub rsp, 8
mov edi, 22
call operator new(unsigned long)
mov BYTE PTR [rax], 2
mov rdi, rax
add rsp, 8
jmp operator delete(void*)
bad():
push rbp
pxor xmm0, xmm0
push rbx
mov rbx, rdi
sub rsp, 24
mov QWORD PTR [rdi+16], 0
movups XMMWORD PTR [rdi], xmm0
mov edi, 22
call operator new(unsigned long)
mov rdi, QWORD PTR [rbx]
test rdi, rdi
je .L5
mov QWORD PTR [rsp+8], rax
call operator delete(void*)
mov rax, QWORD PTR [rsp+8]
.L5:
mov BYTE PTR [rax], 2
lea rdx, [rax+22]
mov QWORD PTR [rbx], rax
add rax, 1
mov QWORD PTR [rbx+8], rax
mov rax, rbx
mov QWORD PTR [rbx+16], rdx
add rsp, 24
pop rbx
pop rbp
ret
mov rbp, rax
jmp .L6
bad() [clone .cold.25]:
.L6:
mov rdi, QWORD PTR [rbx]
test rdi, rdi
je .L7
call operator delete(void*)
.L7:
mov rdi, rbp
call _Unwind_Resume