我正在尝试引入一个通用函数,其语义类似于三元运算符:
在下面的代码清单中,函数
这是否是GCC可以改进的地方(优化的空间),还是C++标准明确禁止这种优化?
E1 ? E2 : E3
。我发现编译器能够根据三元运算符的条件消除其中一个E2
或E3
的计算。然而,在调用ternary
函数时,即使E2
/E3
没有副作用,GCC也会错过这种优化。在下面的代码清单中,函数
ternary
被编写成与三元运算符类似。但是,GCC会发出潜在的重复调用函数f
的指令,这似乎可以通过消除一些输入值(就像对于三元运算符一样)来实现,因为f
被声明为纯属性,请查看godbolt链接以获取由GCC生成的汇编代码。这是否是GCC可以改进的地方(优化的空间),还是C++标准明确禁止这种优化?
// Very heavy function
int f() __attribute__ ((pure));
inline int ternary(bool cond, int n1, int n2) {
return cond ? n1 : n2;
}
int foo1(int i) {
return i == 0 ? f() : 0;
}
int foo2(int i) {
return ternary(i == 0, f(), 0);
}
使用-O3 -std=c++11
的汇编清单:
foo1(int):
test edi, edi
jne .L2
jmp f()
.L2:
xor eax, eax
ret
foo2(int):
push rbx
mov ebx, edi
call f()
test ebx, ebx
mov edx, 0
pop rbx
cmovne eax, edx
ret
__attribute__ ((const))
来“工作”。 - melpomenemissed-optimization
的错误。https://gcc.gnu.org/bugzilla/enter_bug.cgi?product=gcc。 - Peter Cordesfoo1
改为int t = f(); return i == 0 ? t : 0;
,GCC 就不会对其进行优化(它总是调用f
),但是它会将foo2
编译成jmp foo1
。 - melpomene