我一直被告知编译器足够聪明,可以消除死代码。我写的大部分代码在编译时都有很多已知的信息,但代码必须以最通用的形式编写。我不知道任何程序集,因此无法检查生成的程序集。什么样的代码可以在最终的可执行文件中被有效地消除?
几个例子,但不限于
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)
在main中,该怎么办?链接时间优化是否能有效地消除死代码?什么是编码风格/编译器选项/技巧,以促进死代码消除?
3条答案
按热度按时间5tmbdcev1#
通常情况下,如果你在the
-O
flag上编译,下面的标志会被打开:字符串
-fdce
是Dead Code Elimination的缩写。我建议你编译你的二进制文件有和没有(即。通过显式地关闭)这个选项来确保你的二进制文件是否像你希望的那样优化。阅读关于编译器的different passes:
至于帮助链接器消除死代码,请通过this presentation。两个主要要点是:
用-ffunction-sections -fdata-sections编译你的模块--它没有任何缺点!
您可能还想看看this GCC bug(看看可能会错过哪些优化机会以及原因)。
xurqigkl2#
功能消除
另一种类型的死代码消除,GCC可以删除整个未使用的符号(函数或变量),可以通过以下方式实现:
字符串
如在:How to remove unused C/C++ symbols with GCC and ld?
这些标志在各种GCC -O级别(-O 1、-O2等)by default中未启用。
还如以下所示:GCC LTO是否执行跨文件死代码消除?如果一个函数由于LTO而被内联,那么它就不会被计入编译单元被放置在最终输出中。
让我们尝试一些函数内DCE
让我们来测试一下GCC能做什么或不能做什么。测试LLM模型很无聊。
main.c
型
编译和反汇编:
型
输出量:
型
是的,不见了。
其他一些:
未在
-O3
中删除,它不知道argc
必须为正:型
0x 44在
-O3
中被删除,但在-O4
中没有,所以它可以执行if/else算法:型
0x 33在
-O3
中被删除,因此它可以执行范围和+
:型
0x 33没有被删除,它不能推理
sqrt
:型
hgb9j2n63#
当我在这样的if表达式中使用模板参数常量时,dce(死代码消除)编译器(Linux上的GCC 4.8.1)标志没有帮助,O2,O3优化也没有帮助。我不得不使用模板专门化 Package 器:
字符串
也可以使用宏来避免编译未使用的代码分支,但这取决于编译器(它是在代码中还是在预编译阶段处理宏):
型