为什么不把这个未使用的变量优化掉? [英] Why isn't this unused variable optimised away?

查看:177
本文介绍了为什么不把这个未使用的变量优化掉?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我玩了Godbolt的CompilerExplorer。我想看看某些优化有多好。我的最低工作范例是:

  #include< vector> 

int foo(){
std :: vector< int> v {1,2,3,4,5};
return v [4];
}

生成的汇编器(由clang 5.0.0,-O2 -std = c

  foo():#@foo()
push rax
mov edi ,20
调用operator new(unsigned long)
mov rdi,rax
调用operator delete(void *)
mov eax,5
pop rcx
ret

可以看出,clang知道答案,但在返回之前做了很多工作。在我看来,即使矢量是创建,因为运营商新/删除。

任何人都可以向我解释发生了什么,以及它为什么不只是返回?



由GCC生成的代码(未在此处复制)似乎明确构建了该向量。有人知道GCC不能推断出结果吗?

是一个相当复杂的类,涉及动态分配。虽然 clang ++ 有时可以省略堆分配,这是一个相当棘手的优化,你不应该依赖它。例子:

  int foo(){
int * p = new int {5};
return * p;

$ / code>




  foo():#@foo()
mov eax,5
ret







举例来说,使用 std :: array< T> 不会动态分配) 生成完整内联代​​码

  #include< array> 

int foo(){
std :: array v {1,2,3,4,5};
return v [4];

$ / code>




  foo():#@foo()
mov eax,5
ret







正如 Marc Glisse 所指出的在另一个答案的评论中,这是标准在 [expr.new]#10中所说的内容


允许实现省略对可替换全局分配函数([new.delete.single])的调用, [new.delete.array])。当它这样做时,存储是由实现提供的,或者通过扩展另一个新表达式的分配来提供。这个实现可能会扩展新表达式e1的分配,以便为新表达式e2提供存储空间,如果以下情况属实,则分配不被扩展:[...]


I played around with Godbolt's CompilerExplorer. I wanted to see how good certain optimizations are. My minimum working example is:

#include <vector>

int foo() {
    std::vector<int> v {1, 2, 3, 4, 5};
    return v[4];
}

The generated assembler (by clang 5.0.0, -O2 -std=c++14):

foo(): # @foo()
  push rax
  mov edi, 20
  call operator new(unsigned long)
  mov rdi, rax
  call operator delete(void*)
  mov eax, 5
  pop rcx
  ret

As one can see, clang knows the answer, but does quite a lot of stuff before returning. It seems to my that even the vector is created, because of "operator new/delete".

Can anyone explain to me what happens here and why it does not just return?

The code generated by GCC (not copied here) seems to construct the vector explicitly. Does anyone know GCC is not capable to deduce the result?

解决方案

std::vector<T> is a fairly complicated class that involves dynamic allocation. While clang++ is sometimes able to elide heap allocations, it is a fairly tricky optimization and you should not rely on it. Example:

int foo() {
    int* p = new int{5};
    return *p;
}

foo():                                # @foo()
        mov     eax, 5
        ret


As an example, using std::array<T> (which does not dynamically allocate) produces fully-inlined code:

#include <array>

int foo() {
    std::array v{1, 2, 3, 4, 5};
    return v[4];
}

foo():                                # @foo()
        mov     eax, 5
        ret


As Marc Glisse noted in the other answer's comments, this is what the Standard says in [expr.new] #10:

An implementation is allowed to omit a call to a replaceable global allocation function ([new.delete.single], [new.delete.array]). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended: [...]

这篇关于为什么不把这个未使用的变量优化掉?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆