C编译器优化 - 涉及算术的宏

3
我正在与一位朋友讨论优化问题,需要帮助找到这个问题的答案,并希望能够阅读一些官方文档以进一步了解问题。
我被告知,在生产环境中编译简单程序时(例如:CCOPTS+=-O4,无调试等),以下代码将被优化:
#define COEFFICIENT_F  (5.0f)
...
...
float f = 1.0f / COEFFICIENT_F;

…将自动优化为以下内容:

#define COEFFICIENT_F  (5.0f)
...
...
#define INV_COEFFICIENT_F (0.2f)
float f = 1.0f * INV_COEFFICIENT_F;

如果我正在编译调试版本(例如:CCOPTS+=-O0 DEBUG=-g),那么代码将不会在预处理器级别优化此操作。

因此,我的问题有两个:

  1. 传递给编译器的优化级别是否影响预处理器所做的决策?
  2. 例如,GCC是否会自动执行这样的转换,包括在预处理时预先计算逆系数,并将其存储在我的代码的数据段中,同时通过乘以其倒数而不是除以其倒数进行计算?

谢谢!


看一下这两个的汇编输出并进行比较?fdiv与fmul(或者其他你系统的浮点操作码)可以展示出来。虽然我不能直接回答你的两个问题... - Michael Dorgan
1
可能是常量C表达式在编译时还是运行时计算?的重复问题。 - trojanfoe
2个回答

4

你的答案如下:

  1. 不。预处理是按照标准定义执行的,不受任何优化级别的影响。

  2. 你所指的优化不是在预处理时进行的,而是在从前端到代码生成器的长路中进行的。


我甚至不相信2是一种优化。编译器会看到1.0 / 5.0,无论优化设置如何,都会计算为0.2 - trojanfoe
1
@trojanfoe,该优化称为“常量折叠”,虽然不是非常高级的优化,但仍然有效。一些前端(经过预处理后)可能会执行此类优化,但我认为这是不好的做法。啊,所以是的,它可以在-O0下执行。 - Bryan Olivier
但是这会随着优化器设置的改变而改变吗? - trojanfoe

1
这真的取决于编译器的确切用法和确切环境。在你提供的确切示例中,编译器必须非常愚蠢才能不明白 1.0f/5.0f = 0.2f,就像 1.0f*0.2f = 0.2f 一样(好吧,在这两种情况下,结果可能是 0.1999996 或类似的东西)。
现在,如果我们有一些编译器在编译过程中无法解决的数据:
 float f[] = { 3.1415926f, 1.0f, 9.82f, 1.4142f };
 float res[4]; 

 for(int i = 0; i < 4; i++)
    res[i] = f[i] / COEFFICIENT_F;

vs.

 for(int i = 0; i < 4; i++)
    res[i] = f[i] * INV_COEFFICIENT_F;

它可能会产生一些差异(特别是在较低的优化级别下,因为优化器不会将微不足道的数学运算替换为其他数学运算,直到至少达到-O2)。

这会产生多大的差异取决于处理器架构。

要确定确切的差异,您需要编写一个小程序并进行测量。(不过要做比四个更多的数字!)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接