【发布时间】:2020-05-21 06:26:14
【问题描述】:
我希望 VC++ 发出这样的代码:
vpxor ymm0, ymm0, ymm0
vmovdqa xmm0, xmm7
在人类语言中,我想要一个 32 字节的 __m256i 值,其中最低 16 字节来自另一个变量,最高 16 字节为零。相当于_mm256_castsi128_si256 固有的,只是我需要高128 位为零,而不是未定义。
这是我尝试过的:
_mm256_setr_m128i( low, _mm_setzero_si128() )
_mm256_insertf128_si256( _mm256_setzero_si256(), low, 0 )
上面两行都编译成vinsertf128,比较慢,3-4个周期延迟,比vmovdqa慢很多。 VC++ 2017 有什么解决方法吗?
【问题讨论】:
-
你实际上并不想要
vpxor ymm0, ymm0, ymm0;简单地编写一个 XMM 寄存器使用 VEX 或 EVEX 编码指令,如vmovdqa(不是传统 SSE)已经零扩展到全宽。这就是 128 位 AVX 指令在没有 SSE/AVX 转换惩罚的情况下避免错误依赖的方式。这与在 x86-64 上编写 32 位整数寄存器相同。实际上,将 YMM 寄存器归零的最有效方法是对相应的 XMM 进行异或零处理,因此 AMD CPUs before Zen2 still only need 1 uop. -
至于让编译器不可怕;祝你好运。如果 MSVC 使用
_mm256_setr_m128i和非 rset版本将自己击倒,那么您可能会被搞砸。赞成您的问题,因为它比您想象的更大错过了优化。在 IvB+ 和 Bulldozer/Zen 上使用 1 uop 实现零延迟是可能的。
标签: c++ visual-c++ simd avx2