Why compiler like GCC can not do dead code elimination on vector?

Viewed 200

After trying, I'm wondering why GCC is able to do DCE on unused malloc or new buffer but not on unused vector?

malloc case: https://godbolt.org/z/xKx5Y1

void fun() {
    int *x = (int *)malloc(sizeof(int) * 100);
}

Resulting assembly:

fun():
        ret

new case: https://godbolt.org/z/66drKr

void fun() {
    int *x = new int[100];
}

Resulting assembly:

fun():
        ret

vector case: https://godbolt.org/z/TWhE1E

void fun() {
    vector<int> x(100);
}

Resulting assembly:

fun():
        sub     rsp, 8
        mov     edi, 400
        call    operator new(unsigned long)
        mov     esi, 400
        lea     rdi, [rax+8]
        mov     rcx, rax
        mov     QWORD PTR [rax], 0
        mov     r8, rax
        mov     QWORD PTR [rax+392], 0
        and     rdi, -8
        xor     eax, eax
        sub     rcx, rdi
        add     ecx, 400
        shr     ecx, 3
        rep stosq
        mov     rdi, r8
        add     rsp, 8
        jmp     operator delete(void*, unsigned long)
2 Answers

Since C++14, from new#Allocation:

New-expressions are allowed to elide or combine allocations made through replaceable allocation functions. In case of elision, the storage may be provided by the compiler without making the call to an allocation function (this also permits optimizing out unused new-expression). [..]

Note that this optimization is only permitted when new-expressions are used, not any other methods to call a replaceable allocation function: delete[] new int[10]; can be optimized out, but operator delete(operator new(10)); cannot.

And the default allocator used by std::vector uses the latter, so your suggested optimization is forbidden (since the as-if rule might still apply, but those operators might have been replaced, so it'll be harder to prove that there are no side effects).

If you provide a custom allocator, you might have the expected optimization: Demo.

Well, simply because vector is a class. In other words, a possibly-sophisticated software object. When you instantiate an instance of it, its "constructor" must be called. Lots of things happen that the application programmer purposely does not wish to think about – but the object code to do it must be generated, nonetheless.

Related