可疑代码如下:
float32_t f = someValueFromSomewhere;
f = f * 4;
编译器会优化这个吗?
根据C-Standard(如果我理解正确的话),第二个操作数必须被提升为float32_t
;
因此,乘法必须使用FPU(或fp仿真)完成。
理论上,只需添加一个立即(可能是溢出检查),就可以在普通硬件寄存器中完成操作。 编译器是否允许进行此优化?是否有编译器可以这样做?如果是这样,他们也会认出表达式
f = f * 4.0f;
是否需要避免有关隐式转换的静态代码检查器警告?
一些补充: 我知道从标准的角度来看两条线都是等价的。但显然编译器可以区分它们。所以问题是,优化器第一次被允许看到代码(或更好的内部表示)。
答案 0 :(得分:6)
只有当原始值不是一个次正规值(包括公共零),不是无穷大或NaN,并且结果不溢出时,才将2加到指数而不是乘以4.0。通常,编译器没有此信息。当编译器确实拥有此信息时,允许进行此转换,这并不意味着它是一个好主意。
除非你想到一个特定的执行平台,从它的浮点寄存器中获取f
的值会更便宜,把它移到一个通用寄存器中,添加一个常量,测试特殊情况(见上文),然后回到浮点寄存器,你可以假设所有这些步骤都比浮点乘法更昂贵。只有将浮点运算模拟为一系列位和整数运算才有意义以这种方式“乘以2”来“乘法”。
f = f * 4.0f;
f * 4
相当于f * (float)4
,因此相当于f * 4.0f
。编译器可以将这些表单中的任何一个转换为它将转换另一个表单的相同代码,并且任何非玩具编译器都知道它们是等效的(例如作为constant propagation优化传递的应用程序{{1} })。