当我传递它时,gcc 会优化代码-O2
标志,但我想知道如果我将所有源文件编译为目标文件,然后再链接它们,它实际上可以做到多好。
这是一个例子:
// in a.h
int foo(int n);
// in foo.cpp
int foo(int n) {
return n;
}
// in main.cpp
#include "a.h"
int main(void) {
return foo(5);
}
// code used to compile it all
gcc -c -O2 foo.cpp -o foo.o
gcc -c -O2 main.cpp -o main.o
gcc -O2 foo.o main.o -o executable
通常,gcc 应该内联foo
因为它是一个小函数并且-O2
使-finline-small-functions
, 正确的?但在这里,gcc 只能看到以下代码foo
and main
在创建目标文件之前独立进行,因此不会有任何类似的优化,对吗?那么,这样的编译真的会让代码变慢吗?
不过,我也可以这样编译:
gcc -O2 foo.cpp main.cpp -o executable
这样会更快吗?如果不是的话,这样会更快吗?
// in foo.cpp
int foo(int n) {
return n;
}
// in main.cpp
#include "foo.cpp"
int main(void) {
return foo(5);
}
Edit: 我在看objdump
,其反汇编代码表明只有#include "foo.cpp"
事情成功了。
看来您自己重新发现了有关C和C++使用的单独编译模型的问题。虽然它确实减轻了内存需求(这在其创建时很重要),但它通过仅向编译器公开最少的信息来实现这一点,这意味着无法执行某些优化(如本例)。
较新的语言及其模块系统可以公开尽可能多的必要信息,如果模块进入下一版本的 C++,我们希望能够发挥这些优势......
同时,最简单的事情就是链接时优化。这个想法是,您将对每个 TU(翻译单元)执行尽可能多的优化以获得目标文件,但您还将使用 IR(中间表示,编译器使用它来优化)丰富传统的目标文件(包含程序集) ) 部分或全部功能。
当调用链接器将这些目标文件合并在一起时,它不只是将文件合并在一起,而是合并 IR 表示,重新执行许多优化过程(不断传播、内联……),然后在其上创建程序集自己的。这意味着它实际上不仅仅是一个链接器,而是一个后端优化器。
当然,像所有优化过程一样,这也是有代价的,因此会导致编译时间更长。另外,这意味着编译器and应该向链接器传递一个特殊选项来触发此行为,在 gcc 的情况下,它将是-lto
or -O4
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)