本文最后更新于:2022年5月1日 晚上
〇、前言
今天逛 V2EX 发现了一个很有意思的问题:用 0-a 替换 -a 能提升性能,原帖链接。楼主和评论区大神都做了实验,并讲解了原理(一个是减法 一个直接取反),现在记录下这个奇技淫巧。
一、测试代码
| void func1(double a) { volatile auto a1 = -a; }
void func2(double a) { volatile auto a2 = 0-a; }
|
二、汇编
汇编代码产生于 https://godbolt.org
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| func1(double): push rbp mov rbp, rsp movsd QWORD PTR [rbp-24], xmm0 movsd xmm0, QWORD PTR [rbp-24] movq xmm1, QWORD PTR .LC0[rip] xorpd xmm0, xmm1 movsd QWORD PTR [rbp-8], xmm0 nop pop rbp ret func2(double): push rbp mov rbp, rsp movsd QWORD PTR [rbp-24], xmm0 pxor xmm0, xmm0 subsd xmm0, QWORD PTR [rbp-24] movsd QWORD PTR [rbp-8], xmm0 nop pop rbp ret .LC0: .long 0 .long -2147483648 .long 0 .long 0
|
三、原理
对于浮点数来讲:由于存在 rounding error(化整误差),GDB 对一些操作不会优化。a 取反是和 -0.0 取异或;而 0 - a 调用的是 sub,汇编指令比 -a 要少一条
对于整数而言:0-a、-a 最终都会被优化成一样的汇编代码
四、参考链接
- -a 和 0-a 有什么区别?