GCC可以从最终输出中消除什么样的死代码?

我一直被告知编译器足以消除死代码。 我编写的大部分代码在编译时都知道很多信息,但代码必须以最通用的forms编写。 我不知道任何assembly,所以我无法检查生成的assembly。 什么样的代码可以在最终的可执行文件中有效消除?

几个例子但不限于

f(bool b){ if(b){ //some code }else{ //some code } } f(true); ////////////////////////// template f(){ if(b){ //some code }else{ //some code } } f(); /////////////////////////// 

如果f定义在其他客观代码中并且被调用的f(true)在main中,那该怎么办? 链接时间优化会有效消除死代码吗? 什么是编码样式/编译器选项/技巧,以促进死代码消除?

通常,如果您使用-O标志进行编译,则会打开以下标志:

  -fauto-inc-dec -fcompare-elim -fcprop-registers -fdce [...] 

-fdce代表Dead Code Elimination。 我建议您使用和不使用(即通过显式关闭)此选项来编译您的二进制文件,以确保您的二进制文件是否像您希望的那样优化。

阅读有关编译器的不同传递 :

  • SSA积极的死代码消除。 由`-fssa-dce’选项打开。 此过程执行消除被认为不必要的代码,因为它对程序没有外部可见影响。 它以线性时间运行。

至于帮助链接器消除死代码,请通过此演示文稿 。 两个主要的要点是:

使用-ffunction-sections -fdata-sections编译模块 – 没有任何缺点!

  • 这包括静态库,而不仅仅是二进制文件 – 使您的库用户可以从更有效的死代码删除中受益。
  • 将您的二进制文件与–gc-sections链接,除非您必须链接使用魔术部分的令人讨厌的第三方静态库。

您可能还想看看这个GCC错误 (看看可能错过什么样的优化机会以及为什么)。

您的示例侧重于函数内的死代码消除。

另一种类型的死代码消除,是删除整个未使用的符号(函数或变量),可以通过以下方式实现:

 -fdata-sections -ffunction-sections -Wl,--gc-sections 

如上所述: 如何使用GCC和ld删除未使用的C / C ++符号?

默认情况下 ,不会在各种GCC -O级别(-O1,-O2等)中启用这些标志。

当我在这样的if表达式中使用模板参数常量时,dce(死代码消除)编译器(Linux上的GCC 4.8.1)标志没有帮助和O2,O3优化也没有帮助。 我不得不使用模板专业化包装器:

 template f(); template<> f(){ //some code on true condition } template<> f(){ //some code on false condition } 

此外,还可以使用宏来避免编译未使用的代码分支,但这取决于编译器(无论是在代码中还是在预编译阶段处理的宏):

 template f(){ #if b //some code #elif //some code #endif // b }