C++ SSE移位指令会在后续指令中导致奇怪的输出(-1.#IND00)?

C++ SSE移位指令会在后续指令中导致奇怪的输出(-1.#IND00)?,c++,output,sse,bit-shift,intrinsics,C++,Output,Sse,Bit Shift,Intrinsics,这个错误可能不会出现在所有的机器上,但在我的机器上,我运行了下面的代码并得到了输出(注意值-1.#IND00) 如果我不加评论 __m64 PSLLDm64_IN = _mm_set_pi32(2,4); __m64 PSLLDm64_C = _mm_set_pi32(2,4);//could this be the culprit? __m64 PSLLDm64_r = PSLLD(PSLLDm64_IN, PSLLDm64_C); print_2_32_bit_

这个错误可能不会出现在所有的机器上,但在我的机器上,我运行了下面的代码并得到了输出(注意值
-1.#IND00

如果我不加评论

__m64 PSLLDm64_IN = _mm_set_pi32(2,4);
    __m64 PSLLDm64_C = _mm_set_pi32(2,4);//could this be the culprit?
    __m64 PSLLDm64_r  =  PSLLD(PSLLDm64_IN, PSLLDm64_C);

    print_2_32_bit_int("values int:" , PSLLDm64_IN);
    print_2_32_bit_int("shifts:", PSLLDm64_C);
    print_2_32_bit_int("result: ", PSLLDm64_r);
我得到

input 1 HADDPD:: 10.000000 100.000000
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: 110.000000 23.000000
我想知道如果第32行
\uuuuuum64 PSLLDm64\uc=\umm\uset\upi32(2,4)可能会搞砸吗

下面是完整的代码(它使用g++与
-msse3-mmmx
一起运行),但并非所有的头都是真正必要的

#include <xmmintrin.h>
#include <emmintrin.h>
#include <pmmintrin.h>
#include <stdio.h>
#include <stdint.h>
#include <iostream>

void print_2_64_bit_doubles(const char * label, __m128d m64_r)
{
    double *val = (double *) &m64_r;
    printf("%s: %f %f\n",
       label, val[0], val[1]);
}
void print_2_32_bit_int(const char * label, __m64 m32_r)
{
    int *val = (int *) &m32_r;
    printf("%s: %d %d\n",
       label, val[0], val[1]);
}
__m128d HADDPD(__m128d __X, __m128d __Y)
{
    return _mm_hadd_pd ( __X, __Y);
}
__m64 PSLLD(__m64 __m, __m64 __count)
{
    return _mm_sll_pi32 ( __m,  __count);
}
int main()
{
    //PSLLD-------------------------------------------------------------------
    __m64 PSLLDm64_IN = _mm_set_pi32(2,4);
    __m64 PSLLDm64_C = _mm_set_pi32(2,4);
    __m64 PSLLDm64_r  =  PSLLD(PSLLDm64_IN, PSLLDm64_C);

    print_2_32_bit_int("values int:" , PSLLDm64_IN);
    print_2_32_bit_int("shifts:", PSLLDm64_C);
    print_2_32_bit_int("result: ", PSLLDm64_r);
    //HADDPD------------------------------------------------------------------
    double C1 = 10;
    double D = C1*C1;
    double x = 10;
    double y = 13;

    __m128d HADDPDm64_1 = _mm_set_pd(D,C1);
    __m128d HADDPDm64_2 = _mm_set_pd(x,y);
    __m128d HADDPDm64_r = HADDPD( HADDPDm64_1, HADDPDm64_2);

    print_2_64_bit_doubles("input 1 HADDPD:", HADDPDm64_1);
    print_2_64_bit_doubles("input 2 HADDPD:", HADDPDm64_2);
    print_2_64_bit_doubles("result of HADDPD:", HADDPDm64_r);

    return 0;
}
以及输出

values int:: 4 2
shifts:: 2
result: : 16 8
input 1 HADDPD:: 10.000000 -1.#IND00
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: -1.#IND00 23.000000

使用gcc和g++4.8.1的Windowsx64端口进行测试,得到了预期的结果。只需解压缩归档文件并将路径设置为mingw64\bin。使用诸如-msse4之类的编译器选项告诉编译器您的硬件支持这些指令

2013年5月7日:很抱歉最初的评论不完整。此外,上述答复旨在作为评论而不是答复

Microsoft VS2010从cygwin获得了与您报告的结果相同的错误结果,使用Microsoft调试器很容易找到原因。事实上,编译警告也指出了问题:

warning C4730: 'main' : mixing _m64 and floating point expressions may result in incorrect code
您报告的问题发生在编译器混合生成MMX和x87 FPU指令时。编译器对_m64数据使用MMX寄存器,对浮点数据类型double使用x87 FPU寄存器或更新的XMM或YMM寄存器。英特尔在设计MMX时,决定将x87寄存器重新用于MMX寄存器数据。这样做是为了使操作系统不需要任何更新来支持MMX的使用。此决定的缺点是MMX和x87 FPU指令不能混合使用。为了帮助防止FPU和MMX指令的意外混合,英特尔制造的MMX寄存器加载将相应FPU寄存器的标记字位标记为SNAN(信号NAN)。这就是导致您看到意外输出的原因。某些编译器和构建选项组合可能允许此代码正常运行。在某些情况下,此代码可能起作用的可能原因: 1) 编译器对双精度数据使用XMM或YMM寄存器。 2) 编译器将所有x87 FPU值保留在内存中,不依赖MMX指令中的FPU寄存器状态。 底线是,由编码器来避免允许编译器生成混合MMX和x87 FPU指令的代码的情况。请认真对待“函数“print_2_32_bit_int”没有EMMS指令”或“混合使用m64和浮点表达式可能导致错误代码”等警告。一种可行的方法是完全避免_m64数据类型

Paul R关于使用_mm_empty()的建议解决了Microsoft VS2010的问题。我在“双C1=10”之前加上它,问题就消失了_这里解释了mm_empty


对于您的其他问题,我只对gcc使用命令行,没有IDE。如果添加_mm_empty()或避免混合MMX和x87 FPU代码,旧版本的gcc应该可以正常工作。

使用gcc 4.2.1对我来说很好-您使用的编译器是什么?我想知道您是否需要
_mm_empty()
在64位SIMD之后?当我在命令行中键入
g++-v
时,我得到了
gcc 4.4.1 tdm-2 mingw 32
。我把
\u mm_empty()紧跟在
\uuu m64 PSLLDm64\u r=PSLLD之后(PSLLDm64\u IN,PSLLDm64\u C)和输出的结果相同?可能是我使用的是cygwin mmintrin头和mingw?这让我很吃惊-可能是编译器的问题。我看到的唯一代码错误是
\uuuuum64 PSLLDm64\uc=\umm\uset\upi32(2,4)应该是例如
\uuuuuum64 PSLLDm64\uc=\umm\uset\uPI64x(2)但这不应该引起您的特殊问题。我只是想知道您是否正在使用像codeblocks这样的IDE(这就是我正在讨论的)。我可以将我的工具链更改为mingw64/bin,但我无法让它编译任何东西(例如,它停止运行,说编译失败)。顺便问一下,您使用的是什么IDE?
values int:: 4 2
shifts:: 2
result: : 16 8
input 1 HADDPD:: 10.000000 -1.#IND00
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: -1.#IND00 23.000000
warning C4730: 'main' : mixing _m64 and floating point expressions may result in incorrect code