【问题标题】:Does g++ empty function removal work recursively?g++ 空函数删除是否递归工作?
【发布时间】:2013-12-09 10:37:30
【问题描述】:

据我所知,在以下情况下,启用优化的g++ 将完全删除对bar 的函数调用:

int bar() { }    
int foo() { bar(); }

但是,考虑以下两种情况,bar 定义如上:

案例一:

int foo(int a, int b) {
    if (a > b) bar();
}

案例 2:

int foo() { bar(); }
int foo2() {foo(); }

在情况 1 中,if 语句是否也会被删除,因为即使条件为真,它也会执行死代码?

在案例 2: 中,foo2 内部对 foo 的调用是否会被移除?

【问题讨论】:

  • 看反汇编。并不难看到。
  • 你知道你可以试试看吗?例如,使用 GCC 的 -S 选项来编译而不是汇编,那么您将能够相当容易地阅读它在做什么。
  • @JohnZwinck,我会试试的。我最初对 disas 犹豫不决,因为我不确定要查找什么,因为我猜编译器会内联。
  • 简而言之,您可以期望删除所有代码,但没有任何保证。该标准允许优化范围,但一般不指定何时必须应用它们。因此,您的问题最好根据g++ 观察到的行为来回答——因为您的问题具有该标签。会发生什么取决于版本和编译器标志 - 你为什么不自己尝试一下?另外,“死代码”是指由于在运行时无法满足执行的分支条件而永远无法执行的代码:您只有一个空函数,而不是死代码。
  • 请注意,您看到的并不是专门的“死代码删除”,而是内联无操作的副作用。

标签: c++ c gcc g++


【解决方案1】:

按照 cmets 中的建议,我自己尝试过,似乎在我描述的两种情况下,空函数调用确实被递归地完全删除了,至少对于gcc 4.8.1 和@987654322 @。

我编译了以下两个程序,首先是gcc -S,然后是gcc -S -O2

方案一:

int bar() { }
int foo() { bar(); }
int main() {
    foo();
}

方案二:

int bar() { }

int foo(int a, int b) {
    if (a > b) bar();
}

int main() {
    foo(2,1);
}

我还尝试使用从命令行传入的foo 的参数,以确保删除不是因为传递给foo 的常量。

int main(int argc, char** argv) {
    foo(argc,1);
}

【讨论】:

    【解决方案2】:

    编译器不会删除整个函数,链接器会。

    如果您正在构建可执行文件(或函数未从库中导出),则链接器将删除所有孤立函数。如果没有,那就是一个错误:)。

    顺便说一句,存储函数的地址(例如,在变量中或将其传递给另一个函数)保证该函数将保留。

    编辑 只是,需要明确的是,优化编译器将内联函数,有效地删除它认为必要的函数调用。在上述情况下(超级简单的函数),毫无疑问它将内联它们。顺便说一句,STL 实现(和增强)在很大程度上依赖于这个特性。

    【讨论】:

    • 这不是删除函数,而是删除调用
    • 除非禁用此功能,否则编译器会内联简单函数,删除调用。我会更新答案
    猜你喜欢
    • 1970-01-01
    • 2010-10-11
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多