"最佳"意味着最少的指令(或最少的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空间.)
我知道3种方法,但据我所知,通常只使用前2种方法:
使用andps或屏蔽符号位andnotps.
将值从零减去否定,然后得到原始的最大值并否定.
subps完成才能使用该maxps指令.与选项2类似,将原始值从零减去否定,但随后使用原始值"按位"和"按位" andps.我运行了一个测试,将其与方法2进行比较,除了处理NaNs 之外,它似乎与方法2的行为相同,在这种情况下,结果将NaN与方法2的结果不同.
andps通常比速度快maxps.NaN涉及到s 时,这是否会导致任何意外行为?也许不是,因为a NaN仍然是a NaN,即使它是一个不同的值NaN,对吧?欢迎提出想法和意见.
我正在寻找在SSE寄存器中打包的所有四个浮点数上翻转符号的最有效方法.
我没有在英特尔架构软件开发手册中找到这样做的固有内容.以下是我已经尝试过的事情.
对于每个案例,我在代码上循环了100亿次并得到了指示时间.我试图至少匹配4秒,这需要我的非SIMD方法,这只使用一元减号运算符.
[48秒]
_mm_sub_ps( _mm_setzero_ps(), vec );
[32秒]
_mm_mul_ps( _mm_set1_ps( -1.0f ), vec );
[9秒]
union NegativeMask {
int intRep;
float fltRep;
} negMask;
negMask.intRep = 0x80000000;
_mm_xor_ps( _mm_set1_ps( negMask.fltRep ), vec );
编译器是带有-O3的gcc 4.2.CPU是英特尔酷睿2双核处理器.