我有一长串 OR 和 AND 链接在一起的 C++ 代码行。当然,编译器在优化它方面比我好得多,我不应该试图过度智能。但是,出于学习目的,我想知道表达式是否可以优化,以及编译器在通过 -O3
和 -Os
后如何看待它。
有没有办法做到这一点?我可以将我想要的表达式一个一个地提取出来,然后将它们放入一个新的程序中。
举个愚蠢的例子,如果我有:
if( n < 2 && n < 1 )
我想看到编译器看到了可以简化为:
if ( n < 1 )
编辑: 其他可能发生优化魔术的情况涉及字节移位,例如除以 2 的幂。
一个真实的例子是这样的:
if(((col1 < col2) && (col1 + pdim < col2))
|| ((col2 < col1) && (col2 + pdim < col1))
|| ((row1 < row2) && (row1 + pdim < row2))
|| ((row2 < row1) && (row2 + pdim < row1))){
overlap = false;
}
这段代码检查是否有两个大小为 pdim
的正方形由左上角的坐标 (col1, row1)
, (col2, row2 )
是重叠的。
这主要是为了了解编译器可以为自己做什么,而不是在生产中使用它。当然,自己编写 C 行的优化版本不是一个好主意,因为它只会损害可读性,并且只能节省几微秒的编译时间。但在某些情况下它可能会变得有用,例如,当用 Python 编写时,没有编译器,Cython 不是一个选项,访问优化版本可能会有用。
我目前在 Linux 上使用 GCC,但如果更方便的话,我可以用 Clang 或任何其他替代品做同样的事情。
最佳答案
GCC 的优化过程以一种名为 GIMPLE 的格式处理代码的中间表示。 .
使用 -fdump-* options ,你可以要求 GCC 输出树的中间状态。
例如
测试.cc
#include <iostream>
#include <cstdlib>
int main()
{
int n(rand());
if (n < 2 && n < 1)
std::cout << "OK" << std::endl;
return 0;
}
编译
g++ -O3 -o test1 -fdump-tree-all test.cc
您将获得大量 (!) 文件,其中:
test.cc.165t.optimized
;; Function int main() (main, funcdef_no=1013, decl_uid=21841, cgraph_uid=229) (executed once)
int main() ()
{
int n;
struct basic_ostream & _6;
<bb 2>:
n_4 = rand ();
if (n_4 <= 0)
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
_6 = std::operator<< <std::char_traits<char> > (&cout, "OK");
std::endl<char, std::char_traits<char> > (_6);
<bb 4>:
return 0;
}
因此您可以检查 gcc 执行了哪些优化:
if (n < 2 && n < 1) // optimized in if (n_4 <= 0) ...
有时在 gdb 调试器中运行程序并使用 disassemble/m
命令查看与 C/C++ 代码混合的程序集是一种有效的替代方法。
关于c++ - C/C++ 行的人类可读优化版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22645745/