c24*_*726 0 c c++ optimization assembly inline-assembly
大多数编译器不优化内联汇编代码(VS2015,gcc),它允许我们编写它不支持的新指令.
但什么时候C/C++编译器应该实现内联汇编优化?
决不.这将破坏内联汇编的目的,即完全符合您的要求.
如果要以编译器可以理解和优化的方式使用目标CPU指令集的全部功能,则应使用内部函数,而不是内联asm.
例如,而不是内联asm popcnt,使用int count = __builtin_popcount(x);(在GNU C中编译-mpopcnt).Inline-asm也是特定于编译器的,所以如果有任何内在函数更具可移植性,特别是如果你使用英特尔的x86内在函数,它可以在所有可以针对x86的主要编译器中得到支持.使用 #include <x86intrin.h>,你可以int _popcnt32 (int a)用来可靠地获取popcntx86指令.请参阅Intel的内在函数查找器/指南以及x86标记wiki 中的其他链接.
int count(){
int total = 0;
for(int i=0 ; i<4 ; ++i)
total += popc(i);
return total;
}
Run Code Online (Sandbox Code Playgroud)
用#define popc _popcnt32gcc6.3 编译:
mov eax, 4
ret
Run Code Online (Sandbox Code Playgroud)
popc在Godbolt编译器资源管理器上使用inline-asm定义的clang 3.9:
xor eax, eax
popcnt eax, eax
mov ecx, 1
popcnt ecx, ecx
add ecx, eax
mov edx, 2
popcnt edx, edx
add edx, ecx
mov eax, 3
popcnt eax, eax
add eax, edx
ret
Run Code Online (Sandbox Code Playgroud)
这是内联asm击败常量传播的典型示例,如果可以避免它,为什么不应该将它用于性能:https://gcc.gnu.org/wiki/DontUseInlineAsm.
这是我用于此测试的内联asm定义:
int popc_asm(int x) {
// force use of the same register because popcnt has a false dependency on its output, on Intel hardware
// this is just a toy example, though, and also demonstrates how non-optimal constraints can lead to worse code
asm("popcnt %0,%0" : "+r"(x));
return x;
}
Run Code Online (Sandbox Code Playgroud)
如果您不知道popcnt它对英特尔硬件上的输出寄存器具有错误依赖性,那么您应该尽可能将其留给编译器.
使用编译器不知道的特殊指令是内联asm的一个用例,但如果编译器不知道它,它肯定无法优化它.在编译器擅长优化内在函数之前(例如对于SIMD指令),内联asm对于这种事情更为常见.但是我们现在已经有很多年了,编译器通常对内在函数很好,即使对于像ARM这样的非x86架构也是如此.