我有一个非常简单的使用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是否启用?
答案 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 explorer,gcc8.2 -m32
配置为默认启用SSE2(即使SSE2通常不是32位基准的 not )。
但是,如您在-Q --help=target
输出中所见,gcc6.3 -m32默认情况下不启用SSE2。
在禁用SSE2(显式或根本不启用addpd
)时,我尝试过的所有操作都无法使gcc发出-m32
。 AFAIK,那将是一个错误。