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

标签 c++ c compiler-optimization

由于有符号整数溢出是未定义的行为,我希望下面的三个函数编译为相同或相似的程序集。然而事实并非如此。 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;
}
comparison on compiler explorer
编译器不执行这种优化是否有原因?

最佳答案

这种优化是否正确取决于实现是否保证整数溢出的影响:

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

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

    关于c++ - 为什么乘以常数有符号整数分数没有优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62487615/

    相关文章:

    c++ - 在类中初始化空数组

    c - MSVC 和优化常量表达式

    python - 重启电脑后Linux串口中的C乱码

    javascript - 如何禁用 V8 的优化编译器

    C++ 优化 : avoid a copy operation

    c++ - 均匀实数分布的范围限制是多少?

    c++ - 如何使用互斥量自动交换 3 个进程?

    c++ - 如何理解 "Pass By Reference Within a Function"w3schools示例?

    c - 输入用户的密码并检查它是否包含字符、字母和数字

    c - 复合文字不是文字吗?