c++ - 编译器可以用双打简化表达式吗?
问题描述
我正在阅读这里的代码:
template<typename T> T Math::AngRound(T x) {
static const T z = 1/T(16);
if (x == 0) return 0;
GEOGRAPHICLIB_VOLATILE T y = abs(x);
// The compiler mustn't "simplify" z - (z - y) to y
y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y;
}
在哪里和T
是。double
GEOGRAPHICLIB_VOLATILE
volatile
我想知道,编译器是否允许“简化”z - (z - y)
为y
,这是否被阻止volatile
?如果相关,我对 C++17 标准感兴趣。
检查程序集的 clang 表明 withoutvolatile
-O3
不会导致z - (z - y)
to的简化y
。
另一方面,icc 在这两种情况下都简化了代码:https ://godbolt.org/z/rz7erdhev 。如果使用 volatile,它会增加额外的读取,但不会增加任何实际计算。
解决方案
你正在寻找-ffast-math
. 这是一个简单的演示:
$ cat main.c
int main(int argc, char **argv)
{
double x=argc+0.5;
return x-(x-27.5);
}
首先使用默认的浮点支持编译它:
$ gcc -g -O3 main.c -o main
$ objdump -S -D main > main.default
$ sed -n "296,310p;311q" main.default
int main(int argc, char **argv)
{
double x=argc+0.5;
4f0: 66 0f ef c0 pxor %xmm0,%xmm0
4f4: f2 0f 2a c7 cvtsi2sd %edi,%xmm0
4f8: f2 0f 58 05 b8 01 00 addsd 0x1b8(%rip),%xmm0 # 6b8 <_IO_stdin_used+0x8>
4ff: 00
return x-(x-27.5);
500: 66 0f 28 c8 movapd %xmm0,%xmm1
504: f2 0f 5c 0d b4 01 00 subsd 0x1b4(%rip),%xmm1 # 6c0 <_IO_stdin_used+0x10>
50b: 00
50c: f2 0f 5c c1 subsd %xmm1,%xmm0
510: f2 0f 2c c0 cvttsd2si %xmm0,%eax
}
514: c3 retq
现在用浮点快速支持编译它:
$ gcc -g -O3 -ffast-math main.c -o main
$ objdump -S -D main > main.opt
$ sed -n "308,314p;315q" main.opt
int main(int argc, char **argv)
{
double x=argc+0.5;
return x-(x-27.5);
}
510: b8 1b 00 00 00 mov $0x1b,%eax
515: c3 retq
推荐阅读
- html - 如何将图像和 2 行文本垂直居中?
- webpack - 从 vue-cli 包中排除一些 css 文件
- php - PHPMailer 似乎不适用于 Hostgator 托管
- flutter - 在 Flutter 中将数组绘制到 Draggable 的位置
- asp.net - 网站发布后不加载 Css 和 JS
- arrays - ruby 数组顺序与数字
- c++ - 为什么 read 函数在 sha1 c++ 实现中不起作用?
- powershell - Powershell - 解压缩 7z 文件
- sql - 在 PostgreSQL 中创建序列
- php - 想在 codeigniter 中使用电子邮件和手机登录