7

我目前正在将大型代码库从 VS2013 更新到 VS2019。我遇到的编译器错误之一如下:

intrinsics.h(348): 错误 C3861: '_mm_cvtpd_pi32': 找不到标识符

此内在函数在 Visual Studio 的“emmintrin.h”中定义。我只在针对 64 位构建时收到此错误。仔细观察后发现,在 2013 年至 2019 年期间,emmintrin.h 的定义从此发生了变化:

extern __m64 _mm_cvtpd_pi32(__m128d _A);
extern __m64 _mm_cvttpd_pi32(__m128d _A);
extern __m128d _mm_cvtpi32_pd(__m64 _A);

对此:

#if defined(_M_IX86)
extern __m64 _mm_cvtpd_pi32(__m128d _A);
extern __m64 _mm_cvttpd_pi32(__m128d _A);
extern __m128d _mm_cvtpi32_pd(__m64 _A);
#endif

即:预处理器指令确保这些函数现在仅可用于 32 位目标。产生错误的第 3 方头文件使用这些函数,而与目标无关(64 位或 32 位)。据推测,这里最好的做法是编辑此头文件以确保仅对 32 位目标调用此函数。然而,我更好奇的是,为什么从 2013 年到 2019 年会发生这种变化?我在这里看到了这个函数的描述:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_pi32&expand=1705

它从一开始就不适用于 64 位目标吗?或者它是否已被我需要考虑的 64 位版本替换?

4

1 回答 1

4

我不知道是否有办法让 MSVC 2019 编译这个遗留的 MMX 内在函数。

在 Windows 上使用 64 位代码中的 MMX 指令是安全的,但 MS 并没有使使用 MS 编译器构建此类代码变得容易。较新的 MSVC 可能不支持内在函数;如果您需要使用 MMX 内部函数编译旧代码(如果 MSVC 没有解决方法),请使用更好的编译器(如 clang) 。

(在 x86-64 和 64 位 Windows 的早期历史中,MS 删除了对 MMX 的一些编译器或汇编器支持的事实让一些人担心 Windows 内核可能无法正确地为 x87/MMX 状态进行上下文切换.这种怀疑是没有根据的。如果你可以让 MMX 代码编译/汇编,例如使用其他工具,它仍然可以完美运行。Windows 支持它,长模式下的 x86-64 CPU 仍然完全支持 MMX。我不要使用 Windows,我不记得到底删除了哪种 MMX 支持。)


当然,通常最好使用 SSE2 而不是 MMX,即 epi32 instrinsics 而不是 pi32 (或任何其他整数元素宽度)。SSE2 是 x86-64 的基线,也是双精度 SIMD 所必需的(包括该转换内在)。

该转换的用例(我认为)主要是为了获取 MMX 整数向量,以便与现有的遗留 MMX 向量化代码一起使用。

但在这种特定情况下cvtpd2pi,实际上并不比cvtpd2qd(正常的 SSE2 _mm_cvtpd_epi32)慢 - 两者都是 2 uop,我认为因为即使在 XMM 寄存器域中,它也必须将 32 位整数洗牌到底部。 https://www.uops.info/table.html。与psXMM 寄存器之间的 FP->int 转换是单微指令的版本不同。

MMX 指令的吞吐量比最近 CPU 上的等效 SSE2/3 指令更差(在更少的端口上运行),并且 mov-elimination 对它们不起作用。

于 2020-03-30T15:24:41.310 回答