是否启用了SSE2指令?

时间:2018-08-10 15:09:25

标签: c++ gcc assembly vectorization

我有一个非常简单的使用sse2内部函数的c ++代码(这是我实际工作的一个最小示例)。

#include <xmmintrin.h>
int main(){
    __m128d a = {0,0};
    __m128d b = {1,1};
    __m128d c = a + b;
    int t = c[0] >= 1;
    return t;
}

我想检查添加的内容是否确实已编译为矢量化指令。我用g++ -S test.cpp

编译文件

我对问题的理解是,如果我不将msse2标志放在g ++中,则不会启用sse2。 g++ -Q --help=target

的结果似乎证实了这一点。
  -msse                             [disabled]
  -msse2                            [disabled]
  -msse2avx                         [disabled]
  -msse3                            [disabled]
  -msse4                            [disabled]
  -msse4.1                          [disabled]
  -msse4.2                          [disabled]
  -msse4a                           [disabled]

但是,在查看汇编代码时,似乎使用了addpd指令。

main:
.LFB499:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $80, %rsp
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax
    pxor    %xmm0, %xmm0
    movaps  %xmm0, -48(%rbp)
    movapd  .LC0(%rip), %xmm0
    movaps  %xmm0, -32(%rbp)
    movapd  -48(%rbp), %xmm0
    addpd   -32(%rbp), %xmm0
    movaps  %xmm0, -64(%rbp)
    movsd   -64(%rbp), %xmm0
    pxor    %xmm1, %xmm1
    ucomisd %xmm1, %xmm0
    setnb   %al
    movzbl  %al, %eax
    movl    %eax, -68(%rbp)
    movl    -68(%rbp), %eax
    movq    -8(%rbp), %rdx
    xorq    %fs:40, %rdx
    je  .L3
    call    __stack_chk_fail
.L3:
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE499:
    .size   main, .-main
    .section    .rodata
    .align 16
.LC0:
    .long   0
    .long   1072693248
    .long   0
    .long   1072693248
    .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609"
    .section    .note.GNU-stack,"",@progbits

我在这里看到一个矛盾,这使我认为有些事情我不理解。 sse2是否启用?

1 个答案:

答案 0 :(得分:1)

我无法复制您的结果。

x86-64 g ++确实启用了-msse-msse2。您可以使用-mno-sse在64位模式下禁用 SSE代码源(即使SSE2是x86-64的基准),在这种情况下,gcc使用以下命令实现+运算符x87 fld / faddp

__m128d被定义为具有两个double元素的GNU C本机向量,并且您没有使用任何内在函数。如果您使用_mm_set_pd_mm_add_pd而不是GNU扩展语法,该语法使用{}括号初始化列表和+运算符将它们用作本机向量,您将得到:

<source>:5:13: error: SSE register return with SSE disabled
     __m128d c = _mm_add_pd(a, b);

有趣的是,即使禁用了SSE2,它仍将解析xmmintrin.h且没有错误,但仅在-O0处解析。启用优化后,它会注意到所有这些(内联)函数都将在禁用了SSE的情况下返回SSE寄存器中,即使您不调用它们。

您可以通过自己定义矢量类型来解决此问题
typedef double v2d __attribute__((vector_size(16)))


On the Godbolt compiler explorergcc8.2 -m32配置为默认启用SSE2(即使SSE2通常不是32位基准的 not )。

但是,如您在-Q --help=target输出中所见,gcc6.3 -m32默认情况下不启用SSE2。

在禁用SSE2(显式或根本不启用addpd)时,我尝试过的所有操作都无法使gcc发出-m32。 AFAIK,那将是一个错误。