我可以正确地比较 avx 中的零寄存器吗?

Could I compare to zero register in avx correctly?

我遇到了 AVX 内部指令 _mm256_testc_pd() 的一个非常奇怪的行为。 在这里你可以看到这个函数的描述 https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=AVX,AVX2&text=test&expand=5432

我在我的代码中使用它 2 次,希望看到与零寄存器进行比较的类似结果。

#include <immintrin.h>
#include <stdio.h>

int main(void)
{
    unsigned char arr[32] __attribute__ ((aligned (32)));

    __m256d a, zero;
    int res1, res2;

    memset(arr, 0 , 32);
    arr[0] = 0xff;
    arr[4] = 0xff;
    arr[8] = 0xff;
    arr[12] = 0xff;
    arr[16] = 0xff;
    arr[20] = 0xfd;
    arr[24] = 0xff;
    arr[28] = 0xff;


    zero = _mm256_setzero_pd();
    a = _mm256_load_pd((double *)arr);
    res1 = _mm256_testc_pd(zero, a);
    printf("res1 = %d\n" , res1);

    memset(arr, 0xff, 32);
    a = _mm256_load_pd((double *)arr);
    res2 =  _mm256_testc_pd(zero, a);
    printf("res2 = %d\n" , res2);
    return 0;
}

结果我得到了

res1 = 1
res2 = 0

有人知道为什么会这样吗?我认为在这两种情况下 a 都不等于零。

更新
在评论中讨论后我的问题解决了,但我对函数 _mm256_testc_si256 和 _mm256_testz_si256

有一点误解

例如:

unsigned char arr[32] __attribute__ ((aligned (32)));

    __m256d a, zero;

    int res1, res2;
    memset(arr, 0 , 32);

    arr[0] = 0x80;

    zero = _mm256_setzero_pd();
    a = _mm256_load_pd((double *)arr);

    res1 = _mm256_testc_si256(_mm256_castpd_si256(zero),_mm256_castpd_si256(a));
    res2 = _mm256_testz_si256(_mm256_castpd_si256(zero),_mm256_castpd_si256(a));
    printf("res1 = %d\n" , res1);
    printf("res2 = %d\n" , res2);

输出为

res1 = 0
res2 = 1

而且我认为只有第一个是正确的。那么为什么这个函数会产生不同的输出?

_mm256_testc_pd 仅对每个双精度元素的 符号位 进行操作,因此观察到的行为是正确的。如果你想在每个元素中测试双精度 values 那么首先使用合适的比较指令(例如 _mm256_cmp_pd 和适当的 _CMP_xxx 参数)然后使用 _mm256_testc_pd_mm256_testz_pd 之后,具体取决于您的具体要求。

感谢 Peter Cordes 和其他所有人,我的问题的正确(也是最漂亮)解决方案是

res = _mm256_testz_si256(_mm256_castpd_si256(a), _mm256_castpd_si256(a))