Assembly 为什么具有内存操作数的vpclmulqdq比movdqa+;pclmulqdq?

Assembly 为什么具有内存操作数的vpclmulqdq比movdqa+;pclmulqdq?,assembly,x86,sse,avx,micro-optimization,Assembly,X86,Sse,Avx,Micro Optimization,vpclmulqdq指令有四个操作数,pclmulqdq有三个操作数,所以我认为可以用vpclmulqdq代替movdqa+pclmulqdq,但是实验结果变慢了 但是当我使用vpaddd而不是movdqa+paddd时,我得到的结果更快。所以我对这个问题感到困惑。代码使用如下指令: movdqa %xmm0, %xmm8 # slower movdqa %xmm0, %xmm9 movdqa %xmm0, %xmm10 movdqa %xmm0, %xmm11 paddd (

vpclmulqdq
指令有四个操作数,
pclmulqdq
有三个操作数,所以我认为可以用
vpclmulqdq
代替
movdqa+pclmulqdq
,但是实验结果变慢了

但是当我使用
vpaddd
而不是
movdqa+paddd
时,我得到的结果更快。所以我对这个问题感到困惑。代码使用如下指令:

movdqa %xmm0, %xmm8          # slower
movdqa %xmm0, %xmm9
movdqa %xmm0, %xmm10
movdqa %xmm0, %xmm11
paddd (ONE),  %xmm8
paddd (TWO),  %xmm9
paddd (THREE),  %xmm10
paddd (FOUR),  %xmm11

vpaddd (ONE), %xmm0, %xmm8   # faster
vpaddd (TWO), %xmm0, %xmm9
vpaddd (THREE), %xmm0, %xmm10
vpaddd (FOUR), %xmm0, %xmm11
pxor (%rdi), %xmm8     # would segfault from misaligned %rdi
pxor 16(%rdi), %xmm9
pxor 32(%rdi), %xmm10
pxor 48(%rdi), %xmm11
该代码使用pclmulqdq指令,如:

movdqa %xmm15, %xmm1               # faster
pclmulqdq $0x00, (%rbp), %xmm1
aesenc 16(%r15), %xmm8
aesenc 16(%r15), %xmm9
aesenc 16(%r15), %xmm10
aesenc 16(%r15), %xmm11
movdqa %xmm14, %xmm3
pclmulqdq $0x00, 16(%rbp), %xmm3
aesenc 32(%r15), %xmm8
aesenc 32(%r15), %xmm9
aesenc 32(%r15), %xmm10
aesenc 32(%r15), %xmm11

vpclmulqdq $0x00, (%rbp), %xmm15, %xmm1   # slower
aesenc 16(%r15), %xmm8
aesenc 16(%r15), %xmm9
aesenc 16(%r15), %xmm10
aesenc 16(%r15), %xmm11
vpclmulqdq $0x00, 16(%rbp), %xmm14, %xmm3
aesenc 32(%r15), %xmm8
aesenc 32(%r15), %xmm9
aesenc 32(%r15), %xmm10
aesenc 32(%r15), %xmm11

其他问题:当我使用未对齐的数据时,如何编写类似于
pxor(%rdi),%xmm0
(编者按:从标题中删除,因为除了对齐循环主要部分的指针之外,没有更好的答案。)

我的数据有16位(2字节)对齐。但有时我需要加载数据,然后执行xor操作。所以我不能写这样的代码:

movdqa %xmm0, %xmm8          # slower
movdqa %xmm0, %xmm9
movdqa %xmm0, %xmm10
movdqa %xmm0, %xmm11
paddd (ONE),  %xmm8
paddd (TWO),  %xmm9
paddd (THREE),  %xmm10
paddd (FOUR),  %xmm11

vpaddd (ONE), %xmm0, %xmm8   # faster
vpaddd (TWO), %xmm0, %xmm9
vpaddd (THREE), %xmm0, %xmm10
vpaddd (FOUR), %xmm0, %xmm11
pxor (%rdi), %xmm8     # would segfault from misaligned %rdi
pxor 16(%rdi), %xmm9
pxor 32(%rdi), %xmm10
pxor 48(%rdi), %xmm11
我更改了我的代码,现在代码是正确的,但是我认为可能效率不是很高,所以我应该怎么做

movdqu (%rdi), %xmm0
movdqu 16(%rdi), %xmm13
movdqu 32(%rdi), %xmm14
movdqu 48(%rdi), %xmm15

pxor %xmm0, %xmm8
pxor %xmm13, %xmm9
pxor %xmm14, %xmm10
pxor %xmm15, %xmm11

你在用什么硬件?对于load+ALU的微融合,不同的CPU具有不同的行为。在Haswell和更高版本上,pclmul不能对负载进行微熔断;它作为一个额外的uop进行解码。在IvB和更早版本上,它被微编码为18 UOP。re:第二部分:没有AVX,对于前端瓶颈,即需要一个单独的
movdqu
和未对齐的数据,实际上没有任何解决办法。你能用标量(或未对齐的向量)进行前几次迭代,以便指针在循环中对齐吗?或者你能将数据对齐到16字节而不是16位(2字节)吗?这实际上是两个独立的问题,这是不受欢迎的:。但对于第二部分,请参阅以了解一些讨论。就像我说的,理想情况下,第一个部分向量不对齐,然后在主部分对齐,最后再不对齐。如果您使用的是Intel CPU,那么您可能会在所有2-uop
aes
指令中遇到uop缓存问题,并且两条单独的指令会将这些uop分散到更多的代码大小上?IDK,不太可能。您需要使用性能计数器进行进一步调查。查看您遇到的瓶颈类型。例如,我的答案显示使用
perf
计算周期和UOP来演示mov消除。也相关。特别是在中查看其他链接,但要注意,有一些微妙的事情他没有为Haswell和以后提到。