以下所有说明都做同样的事情:设置%eax为零.哪种方式最佳(需要最少的机器周期)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
Run Code Online (Sandbox Code Playgroud) 在高级向量扩展(AVX)中,比较指令如_m256_cmp_ps,最后一个参数是比较谓词.谓词的选择压倒了我.它们似乎是类型,排序,信号的三重奏.例如_CMP_LE_OS是'小于或等于,有序,信令.
对于初学者来说,是否存在选择信令或非信令的性能原因,同样,有序或无序的速度比另一个更快?
什么'非信令'甚至意味着什么?我根本无法在文档中找到这个.任何关于何时选择什么的经验法则?
以下是avxintrin.h的谓词选择:
/* Compare */
#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */
#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */
#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */
#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */
#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */
#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */
#define _CMP_ORD_Q 0x07 /* Ordered (nonsignaling) */
#define _CMP_EQ_UQ 0x08 /* Equal (unordered, non-signaling) */
#define …Run Code Online (Sandbox Code Playgroud) 我很好奇有多少种方法可以在x86汇编中将寄存器设置为零.使用一条指令.有人告诉我,他设法找到了至少10种方法.
我能想到的是:
xor ax,ax
mov ax, 0
and ax, 0
Run Code Online (Sandbox Code Playgroud) "最佳"意味着最少的指令(或最少的uops,如果任何指令解码到多个uop).机器码大小(以字节为单位)是相同insn计数的平局.
恒定生成本质上是一个新的依赖链的开始,所以延迟很重要.在循环内生成常量也很不寻常,因此吞吐量和执行端口需求也几乎无关紧要.
生成常量而不是加载它们需要更多指令(除了全零或全一),因此它会占用宝贵的uop-cache空间.这可能是比数据缓存更有限的资源.
Agner Fog优秀的优化装配指南涵盖了这一点Section 13.4.表13.10具有用于产生向量序列,每一个元素是0,1,2,3,4,-1,或-2,与从8位到64位单元大小.表13.11具有用于产生一些浮点值序列(0.0,0.5,1.0,1.5,2.0,-2.0,和位掩码为符号位.)
Agner Fog的序列仅使用SSE2,无论是设计还是因为它尚未更新一段时间.
使用短的非显而易见的指令序列可以生成哪些其他常量? (具有不同移位计数的进一步扩展是显而易见的而不是"有趣的".)是否有更好的序列用于生成Agner Fog列出的常量?
如何将128位immediates移动到XMM寄存器说明了将任意128b常量放入指令流的一些方法,但这通常是不合理的(它不会节省任何空间,并占用大量的uop-cache空间.)
要清除所有位,您经常会看到一个独占或在XOR eax, eax.反过来也有这样的伎俩吗?
我能想到的是用额外的指令反转零.