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

时间:2012-05-30 02:56:55

标签: c++ c templates gcc g++

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

几个例子,但不限于

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

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

3 个答案:

答案 0 :(得分:25)

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

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

-fdce代表死法消除。我建议您使用和不使用(即通过明确关闭)此选项来编译您的二进制文件,以确保您的二进制文件是否像您希望的那样进行了优化。

阅读编译器的different passes

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

至于帮助链接器消除死代码,请通过this presentation。两个主要的要点是:

  

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

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

您可能还想查看this GCC bug(了解可能遗漏优化的可能性以及原因)。

答案 1 :(得分:1)

您的示例主要关注函数内的死代码消除。

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

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

如上所述:How to remove unused C/C++ symbols with GCC and ld?

在各种GCC -O级别(-O1,-O2等)by default中未启用这些标志。

答案 2 :(得分:0)

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

template<bool b>
f();

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

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

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

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