当前位置: 首页 > 知识库问答 >
问题:

允许编译器优化浮点常量乘法吗

东方震博
2023-03-14

有问题的代码如下:

float32_t f = someValueFromSomewhere;
f = f * 4;

编译器会优化它吗?根据C-Standard(如果我理解正确的话),第二个操作数必须提升为float32_t;因此乘法必须使用FPU(或fp仿真)完成。

从理论上讲,该操作可以在正常的硬件寄存器中完成,只需添加一个即时的(并且可能是溢出检查)。是否允许编译器执行此优化?是否有已知的编译器这样做?如果是这样,他们是否也会识别该表达式

f = f * 4.0f;

这是避免有关隐式转换的静态代码检查器警告所必需的?

补充一下:我知道从标准的角度来看,这两条线是等价的。但是很明显编译器可以区分它们。所以问题是在什么时候允许优化器第一次看到代码(或者更好地看到它的内部表示)。

共有1个答案

滕成双
2023-03-14

仅当原始值不是次正规值(包括公共零)、不是无穷大或NaN,并且结果没有溢出时,将指数加2而不是乘以4.0才有效。通常,编译器没有这些信息。当编译器确实有这些信息时,它被允许进行这种转换,这并不意味着这是一个好主意。

除非您正在考虑一个特定的执行平台,在这个平台上,从它所在的浮点寄存器中获取f的值,将其移动到通用寄存器中,添加常量,测试特殊情况(见上文),然后返回浮点寄存器会更便宜,您可以假设所有这些步骤都是, 比浮点乘法更昂贵。只有当浮点运算被模拟为一系列位和整数运算时,以这种方式“优化”乘法的二次幂才有意义。

f * 4 等价于 f * (浮点)4,因此等价于 f * 4.0f。编译器可以将这些表单中的任何一个转换为它本来会转换另一个表单的相同代码,并且任何非玩具编译器都知道这些是等效的(例如,作为常量传播优化传递到(float)4的应用程序)。

 类似资料:
  • 我试图检查在哪里失去了准确表示大整数的能力。所以我写了这个小片段: 这段代码似乎适用于所有编译器,除了clang。Clang生成一个简单的无限循环。戈德博尔特。 这是允许的吗?如果是,这是QoI问题吗?

  • 根据这个问题,浮点除法与浮点乘法。由于某些原因,除法比乘法慢。 如果可能的话,编译器通常会用乘法代替除法吗? 例如: 会是: 如果它被认为是编译器可靠的问题,我使用的是VS2013默认编译器。但是,如果我得到一个通用的答案就好了(这种优化的理论有效性)

  • 如果我写 大多数C编译器是否足够聪明,能够将1或-1的乘法优化成更快的运算(无操作或求反)?

  • 我经常注意到gcc在可执行文件中将乘法转换为移位。当将与相乘时,可能会发生类似的情况。例如,可能只是将的指数增加1,从而节省一些周期。如果有人要求编译器这样做(例如,通过),编译器通常会这样做吗? 编译器通常是否足够聪明来执行此操作,还是我需要自己使用或函数系列来执行此操作?

  • 问题内容: 问题说明了一切。有人知道以下内容吗? …被优化成? 编译器会这样做吗?(我的兴趣在于GCC)。在某些情况下会这样做吗?在其他情况下却不会呢? 我真的很想知道,因为每次我写一个像这样可以优化的除法运算时,我都会花些精力思考是否浪费一秒钟宝贵的时间去做一个足以满足需要的除法运算。 问题答案: 即使g++ -O0(是,-O0!),也会发生这种情况。您的函数编译为: 请注意shrq $6,右移

  • 问题内容: 假设我在C代码中有类似的内容。我知道您可以使用a 代替,以使编译器不对其进行编译,但是出于好奇,我问编译器是否也可以解决此问题。 我认为这对于Java编译器来说更为重要,因为它不支持。 问题答案: 在Java中,if内的代码甚至都不是已编译代码的一部分。它必须编译,但不会写入已编译的字节码。它实际上取决于编译器,但我不知道没有对它进行优化的编译器。规则在JLS中定义: 优化的编译器可能