https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104529
Bug ID: 104529 Summary: [missed optimization] inefficient codegen around new/delete Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: tnfchris at gcc dot gnu.org Target Milestone: --- Target: aarch64-* Consider the following example #include <cstdint> #include <cstdlib> #include <vector> struct param { uint32_t k; std::vector<uint8_t> src; std::vector<uint8_t> ref0; }; size_t foo() { param test[] = { {48, {255, 0, 0, 0, 0, 0} }}; return sizeof(test); } where the entire thing should have been elided, but that is already reported in #94294. Instead this code also shows that we are generating quite inefficient code (even at -Ofast) on AArch64 we generate: foo(): stp x29, x30, [sp, -32]! mov w1, 255 <-- 1 mov x0, 6 mov x29, sp str w1, [sp, 24] <-- 1 strh wzr, [sp, 28] <-- 2 bl operator new(unsigned long) ldrh w3, [sp, 28] <-- 2 mov x1, 6 ldr w4, [sp, 24] <-- 1 str w4, [x0] strh w3, [x0, 4] bl operator delete(void*, unsigned long) mov x0, 56 ldp x29, x30, [sp], 32 ret There's no reason to spill and rematerialize a constant when the constant is representable in a single move. It's also unclear to me why it things the 255 and 0 need to be before the call to new. But even if it did need it, it's better to re-create the constants rather than materializing them again. However x86 gets this right, which is why I've opened this as a target bug: foo(): sub rsp, 8 mov edi, 6 call operator new(unsigned long) mov esi, 6 mov DWORD PTR [rax], 255 mov rdi, rax xor eax, eax mov WORD PTR [rdi+4], ax call operator delete(void*, unsigned long) mov eax, 56 add rsp, 8 ret