【问题标题】:At which level is Compiler Optimization applied?编译器优化应用在哪个级别?
【发布时间】:2011-10-13 14:16:20
【问题描述】:

我的问题是编译器在哪个级别应用优化。是在不同的代码文件级别吗?如果是这种情况,那么它是否比在整个代码中应用它更低效?其次,当其中一个源文件在没有优化的情况下编译然后与一个具有 -O3 级别优化的源文件链接时会发生什么?

我特别想知道 gcc 如何处理这些事情。

【问题讨论】:

标签: c optimization gcc compiler-construction


【解决方案1】:

可以使用单独的优化标志编译单独的翻译单元,这通常不是问题。编译时优化通常只影响一个 TU 内的可见代码。

该规则的一个例外是标志-fwhole-program,它表示您的源代码构成了整个程序并允许进行更积极的优化:

gcc -o prog *.c -O3 -fwhole-program -s

也就是说,GCC 最近在 link 时引入了另一层优化;要使用它,请使用 -flto (GCC 4.6) 编译所有内容。但是,这也与每个 TU 的优化标志无关:

gcc -c module1.c -flto -O2
gcc -c module2.c -flto -O3 -fno-strict-aliasing
gcc -c module3.c -flto -O0
gcc -c module4.c -O1
gcc -o prog module*.o -flto -s

最后,你还可以在链接阶段指定一个独立的-O* 选项,但我不知道这是否有什么不同。

还要注意预编译的头文件不能独立优化;只有使用与 TU 相同的优化设置编译 PCH 才符合条件。

【讨论】:

  • 我可以内联对象文件中的函数,即我无权访问其代码的函数吗?
  • 不行,内联只能发生在编译阶段,内联函数定义必须是可见的。这就是传统上将内联函数放在头文件中的原因。
  • 只要调用和被调用的代码对能够(并允许)尝试优化的程序可见,就会发生内联。使用 LTO(不知道这对于今天的 GCC 是否特别适用,但对于 LLVM 绝对适用),像内联这样的优化仍然可以在链接/原始代码生成之前发生(在前端完成很久之后)。但同样,被调用的代码必须以某种形式提供(显然)。
  • 是的,LTO 增加了一些新的可能性。不确定它是否是真正的“内联”,我认为它主要是静态重复删除。但我不太了解 LTO。
  • 再说一次,我不能代表 GCC 的 LTO 通行证,但 LLVM 肯定会看到 C/C++ 级别的函数,并且可以对它们进行所有常见的优化,例如“真正的”函数内联以及非常聪明的函数,如循环不变代码运动。事实上,几乎所有 Clang 的优化(可能在代码生成中保留一些需要特定语言知识的快捷方式)都是通过 LLVM IR 的与前端无关的传递,相当于目标代码(几乎是低级并在最后转换为机器代码)。然而,它通常不比 GCC 慢 10%,而且通常更好。
猜你喜欢
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多