【问题标题】:Dead code elimination in switch statementswitch 语句中的死代码消除
【发布时间】:2015-11-03 15:07:18
【问题描述】:

假设以下函数存在于静态库(*.a、*.lib)中:

int func_foo(int i) {
    switch (i) {
    case 1:
        return foo_bar();
    case 2:
        return foo_baz();
    case 3:
        return foo_bat();
    default:
        return -1;
    }
}

如果这个库的用户调用这个函数并且只传入1,编译器会(或可以)删除对23的调用吗?

如果foo_baz()foo_bat() 函数没有在任何其他函数中引用(也就是死代码消除),编译器是否也会删除它们?

【问题讨论】:

  • “这个库的用户”如何摄取库?引用源代码或一些现成的二进制文件?
  • 假设它是一个已编译的静态库(例如 *.a 或等效的)。

标签: c compiler-optimization c99 dead-code


【解决方案1】:

如果启用Whole Program Optimization 并且func_foo 未标记为从输出共享对象库或DLL 导出,则像MSVC 这样的体面的编译器可以并且将删除这些死代码。因此,代码将如下所示(当然忽略函数内联):

int func_foo(int i) {
    return foo_bar();
}

否则,如果 WPO 未启用且func_foo 具有外部链接(默认),则编译器无法删除死代码。最后,如果未启用 WPO 并且 func_foo 具有静态链接,则编译器可以删除死节点。在最后一种情况下,MSVC 没有执行优化。其他编译器可能会执行它。

编译器是否也会删除 foo_baz() 和 foo_bat() 函数,如果 它们没有在任何其他函数中引用?

同样,它取决于 WPO 是打开还是关闭,如果它关闭,则取决于功能的链接。在任何情况下,都不得导出函数。此外,您必须明确告诉编译器使用编译器开关删除未引用的函数。例如,在 MSVC 中,您必须使用 /Gy 编译器开关和 /OPT:NOREF 链接器开关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多