"最佳"意味着最少的指令(或最少的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空间.)
我一直在尝试使用microsoft的sse内在函数来优化我使用的代码.优化我的代码时最大的问题之一是每当我想使用常量时就会发生LHS.似乎有一些关于生成某些常量的信息(这里和这里 - 第13.4节),但它的所有汇编(我宁愿避免).
问题是当我尝试用内在函数实现相同的东西时,msvc抱怨不兼容的类型等.有没有人知道使用内在函数的任何等效技巧?
示例 - 生成{1.0,1.0,1.0,1.0}
//pcmpeqw xmm0,xmm0
__m128 t = _mm_cmpeq_epi16( t, t );
//pslld xmm0,25
_mm_slli_epi32(t, 25);
//psrld xmm0,2
return _mm_srli_epi32(t, 2);
Run Code Online (Sandbox Code Playgroud)
这会产生一堆关于不兼容类型的错误(__m128 vs _m128i).我对此很陌生,所以我很确定我错过了一些明显的东西.有人可以帮忙吗?
tldr - 如何使用ms intrinsics生成一个填充了单精度常量浮点数的__m128 vec?
谢谢阅读 :)
这是代码
float a = ...;
__m256 b = _mm_broadcast_ss(&a)
Run Code Online (Sandbox Code Playgroud)
总是比这段代码快
float a = ...;
_mm_set1_ps(a)
Run Code Online (Sandbox Code Playgroud)
?
如果a被定义为static const float a = ...而不是float a = ...?