为什么像 GCC 这样的编译器不能对 vector 做无用代码消除?
Why compiler like GCC can not do dead code elimination on vector?
尝试后,我想知道为什么 GCC 能够在未使用的 malloc
或 new
缓冲区上执行 DCE,但不能在未使用的 vector
上执行 DCE?
malloc
案例:https://godbolt.org/z/xKx5Y1
void fun() {
int *x = (int *)malloc(sizeof(int) * 100);
}
生成的程序集:
fun():
ret
new
案例:https://godbolt.org/z/66drKr
void fun() {
int *x = new int[100];
}
生成的程序集:
fun():
ret
vector
案例:https://godbolt.org/z/TWhE1E
void fun() {
vector<int> x(100);
}
生成的程序集:
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)
嗯,仅仅因为 vector
是一个 class。 换句话说,一个可能很复杂的软件对象。当您实例化它的一个实例时,必须调用它的“构造函数”。发生了很多应用程序程序员 故意 不想考虑的事情 – 但是必须生成执行此操作的目标代码。
自 C++14 起,来自 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.
并且默认的 allocator used by std::vector
uses the latter, so your suggested optimization is forbidden (since the as-if 规则可能仍然适用,但这些运算符可能已被替换,因此更难证明没有副作用)。
如果您提供自定义分配器,您可能会进行预期的优化:Demo。
尝试后,我想知道为什么 GCC 能够在未使用的 malloc
或 new
缓冲区上执行 DCE,但不能在未使用的 vector
上执行 DCE?
malloc
案例:https://godbolt.org/z/xKx5Y1
void fun() {
int *x = (int *)malloc(sizeof(int) * 100);
}
生成的程序集:
fun():
ret
new
案例:https://godbolt.org/z/66drKr
void fun() {
int *x = new int[100];
}
生成的程序集:
fun():
ret
vector
案例:https://godbolt.org/z/TWhE1E
void fun() {
vector<int> x(100);
}
生成的程序集:
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)
嗯,仅仅因为 vector
是一个 class。 换句话说,一个可能很复杂的软件对象。当您实例化它的一个实例时,必须调用它的“构造函数”。发生了很多应用程序程序员 故意 不想考虑的事情 – 但是必须生成执行此操作的目标代码。
自 C++14 起,来自 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, butoperator delete(operator new(10));
cannot.
并且默认的 allocator used by std::vector
uses the latter, so your suggested optimization is forbidden (since the as-if 规则可能仍然适用,但这些运算符可能已被替换,因此更难证明没有副作用)。
如果您提供自定义分配器,您可能会进行预期的优化:Demo。