MSVC 如何避免混合 SSE 和 AVX?

问题描述 投票:0回答:1

尽管混合 SSE 和 AVX 编码会受到臭名昭著的惩罚(请参阅为什么在 Skylake 上没有 VZEROUPPER 的情况下这个 SSE 代码会慢 6 倍?),但可能需要混合 128 位和 256 位操作。

可以通过始终使用 AVX 编码(即使是 128-but 操作)或在任何 SSE 编码之前添加

vzeroupper
来避免这种损失。

对于编译器生成的代码,如果启用了 AVX,编译器将假定 AVX 可用,并将使用 AVX 编码。对于每个可以外部调用的函数,编译器都会在末尾插入

vzeroupper

但是,MSVC 允许通过直接使用内在函数来生成未启用 AVX 的 AVX 代码(与其他一些编译器不同,它们需要启用 AVX 的选项才能使用 AVX 内在函数)。

如果在单个函数中使用两个内在函数,如何避免混合 SSE 和 AVX?

c++ visual-c++ sse avx
1个回答
0
投票

编译器将在第一个 AVX 内在函数之后使用 AVX 编码。 例如下面的函数:

void test1(__m256i* dest, char x, char y)
{
        __m256i a = _mm256_broadcastw_epi16(_mm_cvtsi32_si128(x)); // movd then vpbroadcastw
        __m256i b = _mm256_broadcastw_epi16(_mm_cvtsi32_si128(y)); // vmovd then vpbroadcastw
        _mm256_store_si256(dest, _mm256_andnot_si256(a, b));
}

会将第一个

_mm_cvtsi32_si128
编码为
movd
,第二个
vmovd
。它会在最后插入
vzeroupper

如果通过 AVX 寄存器获取参数,它将从一开始就使用 AVX 编码(这使用

__vectorcall
调用约定发生)。同理,如果返回
__m256i
类型,则
vzeroupper
不会插入到最后

这不适用于未优化的编译。使用

/Od
或不使用
/O...
选项,它将仅对任何指令使用最低级别的编码。对于未优化的编译,它也不会在末尾插入
vzeroupper

Godbolt 的编译器浏览器演示。

© www.soinside.com 2019 - 2024. All rights reserved.