为什么乘以常量有符号整数分数没有优化?

Why are multiplications by constant signed integer fractions not optimised?

本文关键字:优化 符号 常量 为什么 整数      更新时间:2023-10-16

由于有符号整数溢出是未定义的行为,我希望下面的三个函数能够编译为相同或相似的程序集。然而,情况并非如此。test2test1略有不同,test3使用其他示例不需要的两个imul指令。

int test1(int x)
{
return x * 5 / 2;
}
int test2(int x)
{
return x * 10 / 4;
}
int test3(int x)
{
return x * 50 / 20;
}

编译器资源管理器上的比较

编译器不执行这种优化有什么原因吗?

这样的优化是否正确将取决于实现是否保证整数溢出的效果:

  1. 如果实现保证整数加法和乘法的行为始终像使用足够大的值来保存结果,然后在每次操作后将 2 的补码截断为类型的大小,则用x*a/b替换x*(m*a)/(m*b)将违反此类保证。
  2. 如果实现保证整数加法和乘法的行为始终像它们产生某个数字一样,但不能保证临时值将被截断为任何特定大小,则此类优化将是有效的。
  3. 如果一个实现不能保证溢出的影响,并要求程序员不惜一切代价避免它们,因为它们可能会导致错误的行为,即使在不使用结果的程序部分,这样的优化将是有效的。

gcc 编译器提供了维护强保证选项 #1 的选项,或者避免提供任何保证,整数溢出破坏不使用结果的代码部分的可能性不仅仅是理论上的。 因为选项 #3 对于从潜在不可信来源接收输入的程序来说是鲁莽危险的,并且因为 gcc 不提供 #1 和 #3 之间的任何设置,所以许多程序,包括选项 #2 满足要求的程序,都是使用fwrapv标志构建的,该标志强制选项 #1。