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

时间:2010-01-06 22:26:52

标签: c++ c compiler-construction assembly micro-optimization

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

8 个答案:

答案 0 :(得分:19)

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

使用-fdump-* family of options,您可以要求GCC输出树的中间状态。

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

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

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

答案 1 :(得分:4)

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

答案 2 :(得分:3)

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

gcc工具链的输出与objdump -dS的粒度不同。获取gcc到输出源和汇编的This article具有与您使用的相同的选项。

答案 3 :(得分:2)

添加-L选项(例如,gcc -L -ahl)可能会提供更易理解的列表。

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


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

游戏开发博客和文章可以成为该主题的一个很好的资源,因为游戏在常量内存中是有效的实时应用程序 - I have some notes on itMike Acton和其他人也是如此。我通常喜欢在浏览列表时将Intel's instruction set reference放在窗口中。

最有用的是首先要对汇编编程有一个良好的基础理解 - 不是因为你想编写汇编代码,而是因为这样做会使读取反汇编变得更加容易。我有a hard time finding一本优秀的现代教科书。

答案 4 :(得分:1)

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

您可以使用Zoom打开对象或可执行文件,并查看编译器对您的代码所做的工作。

答案 5 :(得分:1)

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

  

-fopt-信息优化

查看尚未应用的内容

  

-fopt-INFO-错过

请注意,输出会发送到标准错误流,以便查看您实际需要重定向 :(提示2&gt;&amp; 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一起使用后,您可以检查交错输出,但这不会让您那么远。享受!

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

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