【问题标题】:Compiling before linking prevents optimization在链接之前编译会阻止优化
【发布时间】:2016-02-16 05:44:53
【问题描述】:

考虑类似以下场景:

main.c 包含类似这样的内容:

#include "sub.h"

main(){
    int i = 0;
    while(i < 1000000000){
        f();
        i++;
    }
}

而 sub.h 包含:

void f();

并且 sub.c 包含这样的内容:

void f(){
    int a = 1;
}

现在,如果这些都在一个源文件中,编译器(在我的例子中是 gcc)会注意到 f() 实际上并没有做任何事情并优化循环。但由于编译发生在链接之前,因此在这种情况下无法进行优化。

对于本地包含文件,可以通过包含原始 .c 文件而不是 tan 标头来避免这种情况,但是当包含来自其他库的标头时,这将变得不可能。有没有办法解决这个问题?

【问题讨论】:

  • 寻找链接时间代码生成/链接时间优化。

标签: c compilation linker header-files compiler-optimization


【解决方案1】:

如果我的理解正确,您只想链接您的程序正在使用的库函数。使用 GCC 工具链,这可以通过优化标志实现:

-O2 -fdata-sections -ffunction-sections

第一个标志应该优化掉什么都不做的循环。其他两个标志将每个函数或数据项放入已编译输出文件中自己的部分。这允许链接器执行优化。注意:编译需要更长的时间,您将无法使用 gprof。

您还需要将-gc-sections 标志传递给链接器,这样它就不会包含未使用的函数和数据部分。

总而言之,你会执行:

gcc -O2 -fdata-sections -ffunction-sections main.c sub.c -Wl,-gc-sections

如果您改为调用 GCC 来生成汇编文件,您可以检查它们以发现 _main 没有执行循环或调用函数 f():

$ gcc -O2 -S -fdata-sections -ffunction-sections main.c sub.c -Wl,-gc-sections
$ cat main.s

来源:

【讨论】:

  • 以后会做。感谢您的建设性批评。
【解决方案2】:

编译器无法猜测,也无法对其编译的单个翻译单元之外的内容做出假设。一些工具链(端到端编译器+链接器+支持实用程序)可能检测到一些从源代码构建的项目中的此类情况,取决于他们优化的复杂程度。这不会是常见的,也不能保证。它肯定不会,也不能应用于被链接的不透明的 3rd 方库。

然而,在实践中,您真的会使用导出一些无操作函数的第三方库,希望有人(您的工具链)会注意到并安全地优化它吗?

【讨论】:

  • 谢谢,这回答了我的问题。我很乐意承认这在实践中很少见的案例——这个问题更多是出于好奇而不是出于实际原因。
【解决方案3】:

windows下vs系统有全程序优化

Sqlite使用脚本构建单个C文件进行编译

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2014-07-03
    相关资源
    最近更新 更多