是否启用了 SSE2 指令?

Are SSE2 instructions enabled?

本文关键字:指令 SSE2 启用 是否      更新时间:2023-10-16

我有一个非常简单的 c++ 代码(我实际正在做的事情的最小示例(,使用 sse2 内部函数。

#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?

我无法重现您的结果。

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

__m128d被定义为具有两个double元素的GNU C本机向量,并且您没有使用任何内部函数。 如果你使用_mm_set_pd_mm_add_pd而不是 GNU 扩展语法,后者将它们用作带有{}支撑的 init 列表和+运算符的本机向量,你会得到:

<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))).


在 Godbolt 编译器资源管理器上,gcc8.2 -m32配置默认启用 SSE2(即使 SSE2 通常不是32 位的基线(。

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

当SSE2被禁用时,我尝试过的任何组合都没有让gcc发出addpd(无论是显式启用还是干脆没有启用-m32(。 AFAIK,那将是一个错误。