【发布时间】:2019-07-12 20:32:16
【问题描述】:
从 gcc 的文档来看
如果控制流到达
__builtin_unreachable的点,则程序未定义。
我认为__builtin_unreachable 可以以各种创造性的方式用作优化器的提示。所以我做了一个小实验
void stdswap(int& x, int& y)
{
std::swap(x, y);
}
void brswap(int& x, int& y)
{
if(&x == &y)
__builtin_unreachable();
x ^= y;
y ^= x;
x ^= y;
}
void rswap(int& __restrict x, int& __restrict y)
{
x ^= y;
y ^= x;
x ^= y;
}
gets compiled to (g++ -O2)
stdswap(int&, int&):
mov eax, DWORD PTR [rdi]
mov edx, DWORD PTR [rsi]
mov DWORD PTR [rdi], edx
mov DWORD PTR [rsi], eax
ret
brswap(int&, int&):
mov eax, DWORD PTR [rdi]
xor eax, DWORD PTR [rsi]
mov DWORD PTR [rdi], eax
xor eax, DWORD PTR [rsi]
mov DWORD PTR [rsi], eax
xor DWORD PTR [rdi], eax
ret
rswap(int&, int&):
mov eax, DWORD PTR [rsi]
mov edx, DWORD PTR [rdi]
mov DWORD PTR [rdi], eax
mov DWORD PTR [rsi], edx
ret
我假设stdswap 和rswap 从优化器的角度来看是最佳的。为什么brswap 不被编译成同样的东西?我可以用__builtin_unreachable 编译成同样的东西吗?
【问题讨论】:
-
stdswap和rswap的程序集实际上可以正常工作,即使x和y别名也是如此。如果使用局部变量(即int temp = y; y = x; x = temp;)正常进行交换,GCC 也会愉快地发出与这些函数相同的指令序列——如今,“XOR 交换”在大多数情况下是一种反模式。 -
@ArneVogel 这就是重点,XOR 交换在别名时具有不同的行为,因此编译器可能不会发出与
stdswap相同的指令。我特地选择了一个反模式,以便验证__builtin_unreachable的效果。 -
嗯,我的主要观点是相关性不等于因果关系。我猜想来自
rswap的异或交换优化真的很古老——几乎和过去的稀缺寄存器和相当愚蠢的编译器一样古老——而且 GCC 开发人员后来从未特别关心改进它。许多编译器优化基本上都是启发式算法之上的特殊情况,这两者都必须有人实现,并希望在少数被认为有意义的参考应用程序中展示其好处。
标签: c++ gcc optimization