为什么乘以常量有符号整数分数没有优化?
Why are multiplications by constant signed integer fractions not optimised?
由于有符号整数溢出是未定义的行为,我希望下面的三个函数能够编译为相同或相似的程序集。然而,情况并非如此。test2
与test1
略有不同,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;
}
编译器资源管理器上的比较
编译器不执行这种优化有什么原因吗?
这样的优化是否正确将取决于实现是否保证整数溢出的效果:
- 如果实现保证整数加法和乘法的行为始终像使用足够大的值来保存结果,然后在每次操作后将 2 的补码截断为类型的大小,则用
x*a/b
替换x*(m*a)/(m*b)
将违反此类保证。 - 如果实现保证整数加法和乘法的行为始终像它们产生某个数字一样,但不能保证临时值将被截断为任何特定大小,则此类优化将是有效的。
- 如果一个实现不能保证溢出的影响,并要求程序员不惜一切代价避免它们,因为它们可能会导致错误的行为,即使在不使用结果的程序部分,这样的优化将是有效的。
gcc 编译器提供了维护强保证选项 #1 的选项,或者避免提供任何保证,整数溢出破坏不使用结果的代码部分的可能性不仅仅是理论上的。 因为选项 #3 对于从潜在不可信来源接收输入的程序来说是鲁莽危险的,并且因为 gcc 不提供 #1 和 #3 之间的任何设置,所以许多程序,包括选项 #2 满足要求的程序,都是使用fwrapv
标志构建的,该标志强制选项 #1。
相关文章:
- 空基优化子对象的地址
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 将无符号char*转换为std::istream*C++
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- vscode g++链路故障:体系结构x86_64的未定义符号
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 为什么乘以常量有符号整数分数没有优化?
- 如何通过组合红色和蓝色无符号字节来优化混合?
- 程序在没有调试符号的情况下崩溃,运行良好(两种情况下都没有优化或任何内容)
- 在没有优化的程序上使用gdb进行调试,但在当前上下文中仍然没有局部变量的符号
- 现代编译器是否优化了for循环中使用的无符号int
- 如何在没有调试符号和优化的情况下创建 cmake 构建配置
- 微优化指针+无符号+1
- 有符号整数溢出为负数:这是一个编译器错误,还是我误解了优化
- 如何使c++编译器使用无符号到有符号的技巧来优化比较
- 优化弱符号查找
- 您将如何编写可能优化为一条SSE指令的无符号加法代码