何时将在C/C 源中优化汇编代码
When will compilers optimize assembly code in C/C++ source?
大多数编译器都不优化内联汇编代码(VS2015,GCC),它允许我们编写新指令不支持。
但是C/C 编译器何时应实现内联装配优化?
永远不会。那将打败直列组装的目的,那就是要准确地获得您的要求。
如果要以编译器可以理解和优化的方式使用目标CPU指令集的全部功能,则应使用内在功能,而不是Inline ASM 。
例如。而不是用于popcnt
的Inline ASM,使用int count = __builtin_popcount(x);
(用-mpopcnt
编译的GNU C中)。Inline-ASM也是特定于编译器的,因此,如果有任何固有的东西更便携,尤其是如果您使用Intel的X86 Intrinsics,这些X86 intersics在所有可以针对X86的主要编译器中都得到了支持。使用#include <x86intrin.h>
,您可以使用int _popcnt32 (int a)
可靠地获取popcnt
X86指令。请参阅英特尔的内在查找器/指南,以及x86标签Wiki中的其他链接。
int count(){
int total = 0;
for(int i=0 ; i<4 ; ++i)
total += popc(i);
return total;
}
用gcc6.3编译的#define popc _popcnt32
:
mov eax, 4
ret
clang 3.9在Godbolt编译器探险器上具有popc
的内联定义:
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
这是内联ASM击败常数传播的一个经典示例,如果可以避免的话,为什么不应该将其用于性能:https://gcc.gnu.org/wiki/wiki/dontuseinlinlinlinlinlinlinlinelineasm。
这是我用于此测试的内联定义:
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;
}
如果您不知道popcnt
对其在英特尔硬件上的输出寄存器有错误的依赖性,这就是您应尽可能将其留给编译器的另一个原因。
使用编译器不知道的特殊说明是Inline ASM的一个用例,但是如果编译器不知道它,则肯定无法优化它。在编译器擅长优化内在(例如,用于SIMD指令)之前,此类内容的内联ASM更为普遍。但是现在我们已经有很多年了,而且编译器通常具有内在的效果,即使对于诸如ARM等非X86架构。
通常,编译器不会优化内联汇编的内容。也就是说,它们不会在您的组件块中删除或更改指令。特别是,gcc
只需通过未改变的内联装配的主体到基础组件(在这种情况下为gas
)。
但是,好的编译器可能会在您的内联装配中优化,在某些情况下,甚至可以完全省略执行内联合代码!例如,如果海湾合作委员会确定组件的声明输出已死,则可以做到这一点。它还可以将一个组件块从循环中提升,或将多个呼叫组合到一个呼叫中。因此,它永远不会弄乱块内的说明,但是更改将执行块的次数的次数是完全合理的。当然,如果块具有其他重要的副作用,也可以禁用此行为。
扩展的ASM语法上的GCC文档有一些很好的例子。
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- SSE 内联汇编和可能的 g++ 优化错误
- 何时将在C/C 源中优化汇编代码
- x86 汇编和优化代码中的 for 循环
- x86汇编指令优化
- 优化器:优化内联汇编