【问题标题】:Do intel C++ compiler optimize out functions that have never been called in the codes?英特尔 C++ 编译器会优化代码中从未调用过的函数吗?
【发布时间】:2012-11-23 12:36:19
【问题描述】:

只是一些优化注意事项:

有谁知道英特尔 C++ 编译器(例如 ICC 13.0,当然,使用 /O3 等一些优化选项编译)是否会自动优化掉任何未使用/未调用的结构/类/函数/变量下面的 examplefun() 之类的代码:

         //...defining examplefunc()....//

         const int a=0;
         if (a>0) 
            int b=examplefunc();

【问题讨论】:

    标签: c++ optimization compiler-construction intel


    【解决方案1】:

    编译器通常不会优化未使用的函数,除非它们是static,因此只能在特定模块中访问。但是,如果链接是在函数级别而不是模块级别完成的,则链接器可能会死剥离函数。

    您可以检查程序集输出、链接器映射或使用objdump 之类的东西来检查函数是否包含在链接的二进制文件中。

    【讨论】:

      【解决方案2】:

      我认为这个问题的表述不正确。虽然问题从字面上询问编译器是否会优化未使用的函数,但这是只有链接器才能做到的事情。

      那么编译器能做什么呢?编译器可以优化死代码,例如在上面的代码中,并且因为已知a0,编译器可以完全删除if 语句。对于大多数用途来说,这已经足够好了(函数是否成为可执行文件不会对性能产生太大影响,是否避免分支会影响函数的性能——尤其是分支错误预测)。

      另外,如果编译器对上面的分支进行优化,程序中会少一个对exampleFunc函数的引用,而在链接器处理生成的二进制文件时,如果整个程序中没有一个函数的引用,它可以完全删除符号。请注意,这只能作为程序链接的一部分来完成,对于库,即使现在没有调用该函数,稍后与该库链接的程序也可能会使用它。

      所以回到最初的问题,编译器将优化分支,而链接器可能或不从二进制文件中删除该函数,但这并不重要。

      关于其他构造,对于structclass,唯一能使其成为二进制文件的是成员函数,同样的事情也适用于那里:如果你正在链接程序并且没有任何函数是使用时,链接器可以删除符号。

      【讨论】:

      • 嗯,我觉得这种区别有点平庸。整个工具链就是“编译器”,它本身就有“编译器”和“链接器”(以及“预处理器”等)。我们可以推断出上下文的含义。
      • @GManNickG:虽然我同意两者都是工具链的一部分,但如果您打算通过检查生成的对象来检查这一点,则差异很重要,该函数将在那里(编译器无法知道是否不同的 TU 使用它)但这并不意味着链接器不会丢弃它。
      • 您在回答中提出问题(“编译器”的定义)。我是说 OP 很可能意味着(并且可能意味着,并且我会以相同的方式和意思编写)英特尔编译器包括所有阶段(“预处理器”、“编译器”、“链接器”)。 “编译器”这个词被重载以表示多种事物,但是您(不合理地,IMO)只假设一个恰好使 OP 错误的定义。如果你明白我的意思,我觉得它“不公平”。并不是说你的定义是“错误的”,只是它不是唯一的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-14
      • 2011-02-14
      • 1970-01-01
      • 2018-08-03
      • 2020-11-25
      相关资源
      最近更新 更多