通过分析程序集列表validationgcc / g ++中的编译器优化

我刚刚问了一个与编译器如何优化某些C ++代码有关的问题,我正在寻找有关如何validation编译器是否已执行某些优化的任何问题。 我试图查看用g ++( g++ -c -g -O2 -Wa,-ahl=file.s file.c )生成的汇编列表g++ -c -g -O2 -Wa,-ahl=file.s file.c什么,但输出太神秘了对我来说。 人们使用什么技术来解决这个问题,是否有任何关于如何解释优化代码的汇编列表或特定于GCC工具链的汇编列表来讨论这个问题的任何好的参考?

GCC的优化传递以一种称为GIMPLE的格式处理代码的中间表示。

使用-fdump-*系列选项 ,您可以要求GCC输出树的中间状态。

例如,将其提供给gcc -c -fdump-tree-all -O3

 unsigned fib(unsigned n) { if (n < 2) return n; return fib(n - 2) + fib(n - 1); } 

并观察它从简单的指数算法逐渐转变为复杂的多项式算法。 (真!)

一种有用的技术是在良好的采样分析器下运行代码,例如在Linux OS下使用Zoom或在Mac OS X下使用Instruments(使用Time Profiler仪器)。这些分析器不仅向您显示代码中的热点,还将源代码映射到反汇编对象码。 突出显示源行显示映射到源行的生成代码的(不一定是连续的)行(反之亦然)。 在线操作码参考和优化提示是一个很好的奖励。

不是gcc,但是在Visual Studio中调试时,您可以选择散布程序集和源代码,这样可以很好地了解为什么语句生成的内容。 但有时它并没有完全正确对齐。

gcc工具链和objdump -dS的输出不是同一粒度。 关于将gcc用于输出源和汇编的这篇文章与您使用的选项相同。

添加-L选项(例如, gcc -L -ahl )可以提供稍微更清晰的列表。

等效的MSVC选项是/FAcs (它更好一点,因为它散布了源,机器语言和二进制文件,并包含一些有用的注释)。


大约三分之一的工作包括完成你正在做的事情:处理C代码,然后查看程序集输出以确保它已经被正确优化(这对于在整个地方编写内联汇编是首选)。

游戏开发博客和文章可以成为这个主题的一个很好的资源,因为游戏在常量内存中是有效的实时应用程序 – 我有一些注释 , Mike Acton和其他人也是如此。 我通常喜欢在浏览列表的同时在一个窗口中保留英特尔的指令集参考 。

最有用的是通常首先对汇编编程有一个良好的基础理解 – 不是因为你想编写汇编代码,而是因为这样做会使读取反汇编更加容易。 我很难找到一本好的现代教科书。

在另一个答案中提到了从RotateRight( http://rotateright.com )的缩放,但为了扩展它:它向他们展示了他们称之为“代码浏览器”的源到汇编的映射。 即使您不是asm专家,它也非常方便,因为他们还将组件文档集成到应用程序中。 汇编列表注释了几种CPU类型的注释和时序。

您只需使用Zoom打开对象或可执行文件,然后查看编译器对代码执行的操作。

要输出应用的优化,您可以使用:

-fopt-信息优化

查看那些尚未应用的内容

-fopt-INFO错过

请注意输出发送到标准错误流,以便看到它实际上必须重定向 :(提示2>&1)

这是一个很好的例子:

 g++ -O3 -std=c++11 -march=native -mtune=native -fopt-info-optimized h2d.cpp -o h2d 2>&1 h2d.cpp:225:3: note: loop vectorized h2d.cpp:213:3: note: loop vectorized h2d.cpp:198:3: note: loop vectorized h2d.cpp:186:3: note: loop vectorized 

你可以检查交错输出,当使用-gobjdump -dS|c++filt ,但这不会让你那么远。享受!

Victor,在您的情况下,您正在寻找的优化只是堆栈上较小的本地内存分配。 如果空类的空间被优化掉,您应该在函数入口处看到较小的分配,在函数出口处看到较小的释放。

至于一般性的问题,我已经阅读(和编写)汇编语言超过(gulp!)30年,我只能说它需要练习,尤其是阅读编译器的输出。

而不是尝试读取汇编程序转储,而是在调试器中运行程序。 您可以暂停执行,单步执行指令,在要检查的代码上设置断点等。许多调试器可以在生成的程序集旁边显示原始C代码,以便您可以更轻松地查看编译器为优化代码所做的工作。

此外,如果您正在尝试测试特定的编译器优化,您可以创建一个简短的虚拟函数,其中包含适合您感兴趣的优化的代码类型(而不是其他,更简单的是,程序集更容易读取)。 通过优化和一次关闭程序编译程序一次; 在构建之间比较生成的虚拟函数的汇编代码应该显示编译器的优化器所做的事情。