x86 SIMD指令集的C接口命名规则
最近因为项目需要,去看了一下libsodium库的实现,发现里面各种宏定义骚操作真是肯尼迪坐敞篷车,脑洞大开啊。
其中负责加解密一块的逻辑使用了硬件指令集来加速,用到了AES专用指令集一类的。作为专用硬件指令集,调用方法之一自然是在代码里写__asm__
了,然而这样会让代码显得很丑,逻辑也不够清晰。于是另一种方法就是封装,反正原理大家都懂,调用的时候做成黑盒就好看多了,于是就有了各种XXXintrin.h
,封装了从MMX、SSE直到AVX等SIMD指令集的C语言接口函数。
然而大家似乎并不关心这些函数的命名规则,亦或者说是这个领域的工作者足够细心严谨,所有人都是先读完intel的手册再开始干活的,以至于当我习惯性地试图从函数名推断出这个函数的功能或者数据特征的时候,一脸茫然= =
根据 牙膏厂的官方文档 所说,这些过渡函数的命名是三段式的:
Most intrinsic names use the following notational convention:
_mm_<intrin_op>_<suffix>
第一段是固定的_mm
,然而intel并没有解释这个mm
是什么含义,我个人猜测是同MMX中的Multi-Media
,作为一种历史习惯遗留下来;第二段是函数对应汇编指令的功能;而第三段表示的是该汇编指令接收的数据格式与类型,进一步由两部分组成。
以文中提到的_mm_set_pd
为例,该函数的作用是从内存中加载两个双精度浮点数据到128位的SIMD寄存器。同样地,以AES-NI指令集的核心指令之一AESENC
来说,它的C形式是_mm_aesenc_si128
,表示该函数对应的指令为AES一轮加密(_aesenc
),传入的数据应该是一个完整(_s
)的128位整型数据(i128
)。
然而,AVX系列的函数可能并不完全遵循如上规则。比如说涉及数据类型转换的_mm256_castps256_ps128
,功能是将一组256位单精度浮点转换为一组128位单精度浮点数(看描述,似乎就是舍弃了高128位?),该函数的第三段_ps128
代表的不再是输入数据格式,而是输出数据格式了。
类似地,AVX512的函数前缀就变成了_mm512
,应该就是和对应的数据宽度为512相关联吧。