像_mm_set_epi32(int, int, int, int) 这样的东西作为单个机器指令毫无意义。它需要四个 r/m32 或仅寄存器源操作数(和一个 XMM 目标),但 x86 机器代码最多只有 3 个操作数包括目标。 (尽管对于 FMA,所有 3 个都是输入)。唯一的例外是 vblendvps/pd 和 vpblendvb,其中一个立即字节编码了第 4 个操作数,但总共仍然只有 4 个,而不是 4 个 reg/mem 和一个单独的目标。
另请参阅Why isn't movl from memory to memory allowed? 和 What kind of address instruction does the x86 cpu have?
而且您经常_mm_set 使用常量,并希望编译器进行常量传播以使单个向量常量。如果你想要一个聚集负载的指针,你可以使用 _mm_i32gather_epi32 和一个索引向量。
所以通常不,它们不是计划的未来指令的占位符,它们基本上只是便利函数,其实现可能会根据输入操作数是在内存中还是在寄存器中而有很大差异。 (例如矢量洗牌)。并且取决于可用的功能级别,例如SSE4.1 pinsrd 可用作_mm_set_epi32(0,0,b,a) 的一部分。
或者像_mm_sin_ps 这样的SVML 数学函数的原型,根本不是真正的内在函数。英特尔使用相同的_mm 命名方案,并将其包含在内部函数指南的一部分中,部分是为了方便使用英特尔自己的编译器(随 SVML 提供)的人们,也可能部分是为了欺骗/诱骗人们依赖英特尔 API使他们的代码更难移植到具有内在函数但没有 SVML 的其他编译器。
或者他们是像_mm256_castsi256_si128这样的强制转换,在 asm 中是免费的,只需使用寄存器的 XMM 低半部分。
C 内部函数 API 甚至没有办法请求 __m128,其中低元素是标量 float,而高元素是无关紧要的,你只有 _mm_set1_ps 广播或_mm_set_ss 零扩展,如果您只将__m128 用于不关心上部元素的事物,并非所有编译器都可以优化它。 (Clang 的 shuffle 优化器可以看到发生了什么。)这很烦人,因为寄存器中的标量浮点 是 只是 XMM 的低元素,但没有等价于 _mm256_castps128_ps256 (它给你一个向量有一个不关心的上半部分)。
未来的 CPU 可能会引入类似 vsinps 的指令来在硬件中完成 SVML 库函数所做的事情,但不太可能。 sin 对于一个合理长度的流水线执行单元来说工作量太大了。例如,x87 fsin 在 Skylake 上被微编码为 53-105 微秒(https://agner.org/optimize/ / https://uops.info/),它通常不会比优化良好的软件实现更快。完整的硬件/微代码 fsin 对于用 asm 编写的玩具程序很方便,但对于将其留给编译器/数学库的实际代码来说,这两种方式都不是什么大问题。
此外,在硬件/微码中执行sin 以可能不是人们想要的方式确定速度与精度的权衡。也相关:Intel Underestimates Error Bounds by 1.3 quintillion - fsin 对于非常接近 Pi 的输入非常不准确,英特尔最近才修复了他们的文档。 (虽然您可以使用扩展精度来获得准确度,但软件的时间并不容易。)据推测,同一指令的 SIMD 浮点版本也会有同样的准确度问题。