什么是内在函数的SSE2程序集?

Fig*_*ron 1 assembly sse simd intrinsics sse2

我正在使用Fasm(程序集),我正在寻找这些内在指令的SSE2汇编指令:

_mm_set1_epi8
_mm_cmpeq_epi8
_mm_movemask_epi8
Run Code Online (Sandbox Code Playgroud)

我从哪里得到它们(网站,pdf ......)?

Pau*_*l R 6

使用英特尔内在函数指南,但请注意,某些内在函数不会映射到单个指令,例如_mm_set1_epi8.对于大多数内在函数,虽然描述列出了相应的机器指令.

您还可以使用疯狂有用的编译器资源管理器来查看给定内部函数的生成代码,例如,此示例_mm_set1_epi8.


Pet*_*des 6

不用去搞弄内在文档,而是首先在他们的x86软件开发人员手册vol.2中查看英特尔的asm文档。或仅在https://www.felixcloutier.com/x86/index.html上没有说明和附录的HTML摘录。例如https://www.felixcloutier.com/x86/PCMPEQB:PCMPEQW:PCMPEQD.html

(Intel的asm手册条目在条目的底部列出了该指令的内在函数。由于AVX512是主PDF的一部分,所以列表变得一团糟,但是如果您已经在另一方向检查了您的猜测/记忆,猜出将用于内部指令的指令并查找它。 或者,如果您搜索完整的PDF版本,您将获得内部名称的称号,因为直接映射到一条指令的内部指令(如_mm_cmpeq_epi8not set1

它比其内在文档更好/更详细(例如,“操作”部分始终存在,并且通常更为具体)。另外,它还向您显示了操作数的顺序。这通常与内在函数匹配,但是我似乎还记得有这种情况的情况,可能是改组。当然,vfmadd132psvs。vs vfmadd213ps.的vfmadd231ps区别在于加数或被乘数之一是目的地,哪些可以是内存。

它还显示了哪个操作数可以是内存。例如,它并不总是最后一个VBLENDVPS xmm1, xmm2, xmm3/m128, xmm4(因为最后一个操作数是在立即字节中编码的,而不是像非VEX版本那样隐式地被xmm0编码)。另外,pmovzxbd xmm1, dword [rdi]其他方法也可以用作狭窄的负载(因为它小于16个字节,因此不需要对齐),但是您永远不会从仅向其提供__m128i源代码的内在函数中得知这一点。使用后编译器不能总是优化为内存操作数_mm_cvtsi32_si128 (int a)

pblendvb在非VEX形式的地方PBLENDVB xmm1, xmm2/m128, <XMM0>,隐式地使用XMM0作为混合控制向量。内在函数也将其隐藏起来,因此,如果您尝试编写,则会出现令人困惑的错误pblendvb xmm1, xmm8, xmm7

Agner Fog的asm优化指南中也有一章是关于SIMD的,其中有一些相当不错的数据移动指令表,这些表对于不同种类的任务很有用。

有关更多链接,另请参见SO x86标签Wiki


我发现更容易记住asm助记符。它们更短,并且在命名方面(如大多数情况下,直到AVX ...),像改组与置换之类的怪异差异要少一些。更重要的是,我倾向于考虑asm,然后编写可让编译器有效编译的内在函数。

CPU延迟/吞吐量/执行端口信息全部是助记符,而不是固有的(Agner Fog的表,instlatx64http://uops.info/),因此您必须知道这些名称才能了解真正的低级性能细节。 ,并检查编译器是否对您的代码做得很好,并查看perf record/ perf report分析结果,以弄清楚为什么某个地方存在热点。

英特尔在其内在函数指南中具有吞吐量/等待时间数字,但没有执行端口,因此您无法知道两条throughtput=1指令是否可以彼此在同一周期中运行,因此它不是很有用。