可以使用 `_mm256_movemask_ps` 代替未定义的 `_mm256_movemask_epi32` 吗?

Can `_mm256_movemask_ps` be used instead of undefined `_mm256_movemask_epi32`?

无法在 https://software.intel.com/sites/landingpage/IntrinsicsGuide 中找到 _mm256_movemask_epi8 所需的 DWORD 对应项,所以我的问题是是否使用 AVX float _mm256_movemask_ps 是允许的,否则怎么办?

据我所知,_mm256_movemask_epi8 可以完成这项工作,但生成的掩码是 32 位,我需要掩码为 8 位(8 个 DWORD 中的每一个都有一个位)。

我摔跤的片段是这样的:

        } else { // Below: haystack >=128; needle >=4; VECTOR

        // Stage 1: SSE2 or AVX2 i.e. 16 or 32 strides.
        // Stage 2: Dealing with the eventual remainder.
        // The main idea: Stressing the registers as it was done in Quadruplet (the above fastest etude) - outperforms Stephen R. van den Berg's strstr at http://www.scs.stanford.edu/histar/src/pkg/uclibc/libc/string/generic/strstr.c
        // __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b) needs AVX2; the more attractive __mmask8 _mm256_cmpeq_epi32_mask (__m256i a, __m256i b) needs AVX512??
        
// Pattern: "Linus Torvalds" 
// Order4:            [    ] skip 32 if not a single occurrence of 'alds' within YMM + (Order - 1) = 32 + 3 = 35 bytes window:
// Haystack:                                 "otto.......................Torvalds" 
// YMM HaystackVector1:                      "otto.......................Torva" 
// YMM HaystackVector2:                      "tto.......................Torval" 
// YMM HaystackVector3:                      "to.......................Torvald" 
// YMM HaystackVector4:                      "o.......................Torvalds" 
// YMM Vector1:                              "aldsaldsaldsaldsaldsaldsaldsalds" 
// 
// Mask1=(HaystackVector1 eqd Vector1):       0   0   0   0   0   0   0   0     ! 8bit !
// Mask2=(HaystackVector2 eqd Vector1):       0   0   0   0   0   0   0   0     ! 8bit !
// Mask3=(HaystackVector3 eqd Vector1):       0   0   0   0   0   0   0   0     ! 8bit !
// Mask4=(HaystackVector4 eqd Vector1):       0   0   0   0   0   0   0   1     ! 8bit !
// Result=(Mask1 OR Mask2 OR Mask3 OR Mask4): 0   0   0   0   0   0   0   1     ! 8bit !

    size_t YMMchunks = cbTarget/32 -1; // in here, ensured at least 4 chunks; in order to avoid past haystack YMM reads - decrease 1 chunk and finish with Scalar_Quadruplet
    const __m256i last4 = _mm256_set1_epi32(pbPattern[cbPattern - 1 -3]);
    for (size_t i = 0; i < YMMchunks; i += 32) {

    const __m256i HaystackVector1 = _mm256_loadu_si256((const __m256i*)(pbTarget + i + 0));
    const __m256i HaystackVector2 = _mm256_loadu_si256((const __m256i*)(pbTarget + i + 1));
    const __m256i HaystackVector3 = _mm256_loadu_si256((const __m256i*)(pbTarget + i + 2));
    const __m256i HaystackVector4 = _mm256_loadu_si256((const __m256i*)(pbTarget + i + 3));

    const __m256i EQD1 = _mm256_cmpeq_epi32(HaystackVector1, last4);
    const __m256i EQD2 = _mm256_cmpeq_epi32(HaystackVector2, last4);
    const __m256i EQD3 = _mm256_cmpeq_epi32(HaystackVector3, last4);
    const __m256i EQD4 = _mm256_cmpeq_epi32(HaystackVector4, last4);

    const __m256i FinalVector12 = _mm256_or_si256(EQD1, EQD2);
    const __m256i FinalVector34 = _mm256_or_si256(EQD3, EQD4);

    uint32_t mask = _mm256_movemask_epi8(_mm256_or_si256(FinalVector12, FinalVector34));
    //uint8_t mask = _mm256_movemask_ps(_mm256_or_si256(FinalVector12, FinalVector34)); //AVX is 8x4float _mm256_movemask_ps, couldn't find _mm256_movemask_epi32 ! Is it allowed?

    // ...

    }

    // ...

        } //if (cbTarget<128) {

这很好用,您只需要 _mm256_castsi256_ps。与 64 位整数相同,转换为双精度向量并使用 _mm256_movemask_pd.

另一个选择,如果你有 BMI2 support,你可以使用 _mm256_movemask_epi8,然后 _pext_u32 和掩码 0x88888888 来删除你不需要的位,将剩余的 8 位打包到字节中。但是,该指令仅在 Intel 上速度快,在 AMD 上它被解码为许多 micro-ops 并且需要将近 20 CPU 个周期。