说我有这段代码:
#include <cmath>
// ...
float f = rand();
std::cout << sin(f) << " " << sin(f);
由于sin(f)
是定义明确的函数,因此可以轻松优化:
float f = rand();
float sin_f = sin(f);
std::cout << sin_f << " " << sin_f;
这是一个优化,期望现代C ++编译器自行完成是合理的吗?或者,编译器是否无法确定sin(f)
应始终为相等的f
值返回相同的值?
答案 0 :(得分:18)
使用使用默认优化标志构建的g ++:
float f = rand();
40117e: e8 75 01 00 00 call 4012f8 <_rand>
401183: 89 44 24 1c mov %eax,0x1c(%esp)
401187: db 44 24 1c fildl 0x1c(%esp)
40118b: d9 5c 24 2c fstps 0x2c(%esp)
std::cout << sin(f) << " " << sin(f);
40118f: d9 44 24 2c flds 0x2c(%esp)
401193: dd 1c 24 fstpl (%esp)
401196: e8 65 01 00 00 call 401300 <_sin> <----- 1st call
40119b: dd 5c 24 10 fstpl 0x10(%esp)
40119f: d9 44 24 2c flds 0x2c(%esp)
4011a3: dd 1c 24 fstpl (%esp)
4011a6: e8 55 01 00 00 call 401300 <_sin> <----- 2nd call
4011ab: dd 5c 24 04 fstpl 0x4(%esp)
4011af: c7 04 24 e8 60 40 00 movl $0x4060e8,(%esp)
使用-O2
构建:
float f = rand();
4011af: e8 24 01 00 00 call 4012d8 <_rand>
4011b4: 89 44 24 1c mov %eax,0x1c(%esp)
4011b8: db 44 24 1c fildl 0x1c(%esp)
std::cout << sin(f) << " " << sin(f);
4011bc: dd 1c 24 fstpl (%esp)
4011bf: e8 1c 01 00 00 call 4012e0 <_sin> <----- 1 call
从这里我们可以看到,没有优化,编译器使用2个调用,只有1个优化,根据经验,我猜,我们可以说编译器确实优化了调用。
答案 1 :(得分:17)
我非常肯定GCC会将sin
标记为非标准纯属性,即__attribute__ ((pure));
这具有以下效果:
除了返回值之外,许多函数都没有效果,它们的返回值仅取决于参数和/或全局变量。这样的函数可以像算术运算符一样经受公共子表达式消除和循环优化。
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
因此很有可能通过消除公共子表达式来优化这种纯调用。
(更新:实际上cmath正在使用constexpr,这意味着相同的优化)