我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.
当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:
(...)
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>
struct Foo
{
int get() { return 100; }
};
struct Bar
{
int get() { return 999; }
};
using Variant = boost::variant<Foo, Bar>;
int run(Variant v)
{
return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
Foo f;
return run(f);
}
Run Code Online (Sandbox Code Playgroud)
但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?
完整装配输出:
.file "main1.cpp"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1: …Run Code Online (Sandbox Code Playgroud) 所以我正在尝试学习一点装配,因为我需要它用于计算机体系结构类.我写了一些程序,比如打印Fibonacci序列.
我认识到每当我编写程序时,我都会使用这3行(正如我从比较生成的汇编代码中学gcc到的那样C):
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
Run Code Online (Sandbox Code Playgroud)
我有2个问题:
%rbp?使用起来不是很简单%rsp,因为它的内容被移到%rbp了第二行吗?%rsp?我的意思是并非总是16(当我在printf第7行或第8行变量时,我会减去24或减去28我在虚拟机(4 GB RAM),Intel 64位处理器上使用Manjaro 64位
我想研究一下如何将某些C/C++特性转换为汇编,并创建了以下文件:
struct foo {
int x;
char y[0];
};
char *bar(struct foo *f)
{
return f->y;
}
Run Code Online (Sandbox Code Playgroud)
然后我编译了这个gcc -S(并且也试过g++ -S)但是当我查看汇编代码时,我很失望地发现bar函数中的一个微不足道的冗余,我认为gcc应该能够优化掉:
_bar:
Leh_func_begin1:
pushq %rbp
Ltmp0:
movq %rsp, %rbp
Ltmp1:
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movabsq $4, %rcx
addq %rcx, %rax
movq %rax, -24(%rbp)
movq -24(%rbp), %rax
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
popq %rbp
ret
Leh_func_end1:
Run Code Online (Sandbox Code Playgroud)
除其他外,线条
movq %rax, -24(%rbp)
movq -24(%rbp), %rax
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
Run Code Online (Sandbox Code Playgroud)
似乎毫无意义多余.是否有任何理由gcc(可能还有其他编译器)不能/不优化它?
我在llvm clang Apple LLVM 8.0.0版(clang-800.0.42.1)上反汇编代码:
int main() {
float a=0.151234;
float b=0.2;
float c=a+b;
printf("%f", c);
}
Run Code Online (Sandbox Code Playgroud)
我编译时没有-O规范,但我也试过-O0(给出相同)和-O2(实际上计算值并存储它预先计算)
产生的反汇编如下(我删除了不相关的部分)
-> 0x100000f30 <+0>: pushq %rbp
0x100000f31 <+1>: movq %rsp, %rbp
0x100000f34 <+4>: subq $0x10, %rsp
0x100000f38 <+8>: leaq 0x6d(%rip), %rdi
0x100000f3f <+15>: movss 0x5d(%rip), %xmm0
0x100000f47 <+23>: movss 0x59(%rip), %xmm1
0x100000f4f <+31>: movss %xmm1, -0x4(%rbp)
0x100000f54 <+36>: movss %xmm0, -0x8(%rbp)
0x100000f59 <+41>: movss -0x4(%rbp), %xmm0
0x100000f5e <+46>: addss -0x8(%rbp), %xmm0
0x100000f63 <+51>: movss %xmm0, -0xc(%rbp)
...
Run Code Online (Sandbox Code Playgroud)
显然它正在做以下事情: