对齐优化
1. Use .p2align <abs-expr> <abs-expr> <abs-expr>代替align
.
使用 3 个参数进行细粒度控制
-
param1- 与什么边界对齐。
-
param2- 用什么(零或
NOP
s).
-
param3- 如果填充超出指定的字节数,则不对齐。
2. 将常用代码块的开头与缓存行大小边界对齐。
- 这增加了整个代码块位于单个缓存行中的机会。一旦加载到 L1 高速缓存中,就可以完全运行,无需访问 RAM 来获取指令。这对于具有大量迭代的循环非常有益。
3.使用多字节NOP
s 用于填充到减少执行时间NOPs.
/* nop */
static const char nop_1[] = { 0x90 };
/* xchg %ax,%ax */
static const char nop_2[] = { 0x66, 0x90 };
/* nopl (%[re]ax) */
static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
/* nopl 0(%[re]ax) */
static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
/* nopl 0(%[re]ax,%[re]ax,1) */
static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
/* nopw 0(%[re]ax,%[re]ax,1) */
static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
/* nopl 0L(%[re]ax) */
static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
/* nopl 0L(%[re]ax,%[re]ax,1) */
static const char nop_8[] =
{ 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
/* nopw 0L(%[re]ax,%[re]ax,1) */
static const char nop_9[] =
{ 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */
static const char nop_10[] =
{ 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
(upto 10byte NOP
s 代表 x86。来源binutils-2.2.3.)
分支预测优化
Lot of variations between x86_64 micro-architectures/generations. However a common set of guidelines that are applicable for all of them can be summarised as follows. Reference : Section 3 of Agner Fog's x86 micro-architecture manual.
1. 展开循环以避免迭代计数稍高。
-
循环检测逻辑保证仅适用于具有< 64迭代。这是因为如果分支指令单向运行,则该分支指令将被识别为具有循环行为n-1次,然后走另一条路1时间,对于任何n最多 64 个。
这并不真正适用于 Haswell 及更高版本中的预测器,它们使用 TAGE 预测器,并且没有针对特定分支的专用循环检测逻辑。在 Skylake 上,对于没有其他分支的紧密外循环内的内循环来说,迭代计数约为 23 可能是最坏的情况:内循环的退出大多数时候都会错误预测,但行程计数非常低,因此经常发生。展开可以通过缩短模式来提供帮助,但对于非常高的循环行程计数,最终的单个错误预测会在多次行程中摊销,并且需要不合理的展开量才能对此采取任何措施。
2.坚持近跳/短跳。
-
无法预测远跳转,即管道总是在远跳转到新代码段 (CS:RIP) 时停止。无论如何,基本上没有理由使用远跳,所以这基本上是不相关的。
在大多数 CPU 上,通常可以预测具有任意 64 位绝对地址的间接跳转。
但是,当目标距离超过 4GB 时,Silvermont(Intel 的低功耗 CPU)在预测间接跳转方面存在一些限制,因此通过在低 32 位虚拟地址空间中加载/映射可执行文件和共享库可以避免这种情况的发生。 。例如在 GNU/Linux 上通过设置环境变量LD_PREFER_MAP_32BIT_EXEC。有关更多信息,请参阅英特尔的优化手册。