我正在测试一个计算两个char缓冲区的XOR的函数。为了提高速度,我要检查整数指针(32位)和长整数指针(64位)的速度。我使用带有char指针的函数作为参考。当然,我在64位机器上进行测试。
但我没有达到我预期的结果。我最后尝试了这3个功能。当我比较" XOR_Diff_Char"使用" XOR_Diff_Int",我的速度提高了大约3倍,因为功能" _Int"在#34;中为#34;迭代次数减少4次。但是当我比较" XOR_Diff_Int"使用" XOR_Diff_QWORD",改进是5-10%,比我预期的要慢,因为主要" for"在" _QWORD"中迭代次数减少2倍而不是" _Int"。我曾尝试(为了比较速度)使用不同的标志进行编译,在-O0和-O3之间,但我没有发现任何差异。
我在Debian 64bits下使用g ++ 4.9.2-10编译器。我还要换另一面旗帜吗?我想是什么,我错了吗?如果使用32位或64位,编译器是否如此优秀并不重要?
/////////////////////////////////
int XOR_Diff_Int(char *pBuffIn1, char *pBuffIn2, char *pBuffOut, unsigned int sizeBuff)
{
int i = 0;
/* Check errors ... */
int *pBuff1 = (int*)pBuffIn1;
int *pBuff2 = (int*)pBuffIn2;
int *pOut = (int*)pBuffOut;
unsigned int sizeInt = (sizeBuff/sizeof(int));
unsigned int modInt = sizeBuff-(sizeBuff%sizeof(int));
for (i = 0; i < sizeInt; i++, pBuff1++, pBuff2++, pOut++)
*pOut = *pBuff1 ^ *pBuff2;
// If size is not sizeof(int) multiple
for (i = modInt; i < sizeBuff; i++)
pBuffOut[i] = pBuffIn1[i] ^ pBuffIn2[i];
return sizeBuff;
}
/////////////////////////////////
int XOR_Diff_Char(char *pBuffIn1, char *pBuffIn2, char *pBuffOut, unsigned int sizeBuff)
{
int i = 0;
/* Check errors ... */
for (i = 0; i < sizeBuff; i++)
pBuffOut[i] = pBuffIn1[i] ^ pBuffIn2[i];
return 1;
}
/////////////////////////////////
int XOR_Diff_QWORD(char *pBuffIn1, char *pBuffIn2, char *pBuffOut, unsigned int sizeBuff)
{
int i = 0;
/* Check errors ... */
long long int *pBuff1 = (long long int*)pBuffIn1;
long long int *pBuff2 = (long long int*)pBuffIn2;
long long int *pOut = (long long int*)pBuffOut;
unsigned int sizeLong = (sizeBuff/sizeof(long long int));
unsigned int modLong = sizeBuff-(sizeBuff%sizeof(long long int));
for (i = 0; i < sizeLong; i++, pBuff1++, pBuff2++, pOut++)
*pOut = *pBuff1 ^ *pBuff2;
// If size is not sizeof(long long int) multiple
for (i = modLong; i < sizeBuff; i++)
pBuffOut[i] = pBuffIn1[i] ^ pBuffIn2[i];
return 1;
}
修改
我正在使用gcov实用程序,我可以看到_QWORD函数执行的迭代次数比_Int少,所以速度应该是double(尽管函数开销等等)。所以我理解为什么速度在两种情况下都相似。为了测试,我只使用像
这样简单的东西gettimeofday(&t1, NULL);
count = XOR_Diff_Int(pDataIn, prevData, pOut, SIZE);
gettimeofday(&t2, NULL);
改变&#34; _Int&#34;为&#34; _QWORD&#34;并重新编译两种类型的测试。
编辑2:
我不太了解汇编程序,但我比较了两个函数(主要&#34; for&#34;),我得到了这个:
// 64bits XOR
movq (%rsi,%r8,8), %r9
xorq (%rdi,%r8,8), %r9
movq %r9, (%rdx,%r8,8)
addq $1, %r8
cmpl %r8d, %ecx
ja .L8
// 32bits XOR
movl (%rsi,%r8,4), %r9d
xorl (%rdi,%r8,4), %r9d
movl %r9d, (%rdx,%r8,4)
addq $1, %r8
cmpl %r8d, %ecx
jg .L8
所以我理解64bits的情况更快,因为使用8字节指令。我认为这不是&#34;说明&#34;问题,但操作系统或类似的东西。目前我还没有想到这一点。
答案 0 :(得分:1)
您尝试做的事情似乎超越了编译器。赢了。
鉴于以下简单功能:
void f(const char* lhs, const char* rhs, char* out, size_t sz)
{
for (size_t i = 0; i < sz; ++i )
out[i] = lhs[i] ^ rhs[i];
}
并使用-O3 -Wall
与GCC进行编译,编译器吐出nearly 300 lines of assembler:
f(char const*, char const*, char*, unsigned long):
testq %rcx, %rcx
je .L38
leaq 16(%rdi), %rax
leaq 16(%rdx), %r9
cmpq %rax, %rdx
setnb %r8b
cmpq %r9, %rdi
setnb %al
orl %eax, %r8d
leaq 16(%rsi), %rax
cmpq %rax, %rdx
setnb %r10b
cmpq %r9, %rsi
setnb %al
orl %r10d, %eax
testb %al, %r8b
je .L3
cmpq $19, %rcx
jbe .L3
movq %rdi, %r8
pushq %r13
pushq %r12
negq %r8
pushq %rbp
pushq %rbx
andl $15, %r8d
cmpq %rcx, %r8
cmova %rcx, %r8
xorl %eax, %eax
testq %r8, %r8
je .L4
movzbl (%rdi), %eax
xorb (%rsi), %al
cmpq $1, %r8
movb %al, (%rdx)
je .L15
movzbl 1(%rdi), %eax
xorb 1(%rsi), %al
cmpq $2, %r8
movb %al, 1(%rdx)
je .L16
movzbl 2(%rdi), %eax
xorb 2(%rsi), %al
cmpq $3, %r8
movb %al, 2(%rdx)
je .L17
movzbl 3(%rdi), %eax
xorb 3(%rsi), %al
cmpq $4, %r8
movb %al, 3(%rdx)
je .L18
movzbl 4(%rdi), %eax
xorb 4(%rsi), %al
cmpq $5, %r8
movb %al, 4(%rdx)
je .L19
movzbl 5(%rdi), %eax
xorb 5(%rsi), %al
cmpq $6, %r8
movb %al, 5(%rdx)
je .L20
movzbl 6(%rdi), %eax
xorb 6(%rsi), %al
cmpq $7, %r8
movb %al, 6(%rdx)
je .L21
movzbl 7(%rdi), %eax
xorb 7(%rsi), %al
cmpq $8, %r8
movb %al, 7(%rdx)
je .L22
movzbl 8(%rdi), %eax
xorb 8(%rsi), %al
cmpq $9, %r8
movb %al, 8(%rdx)
je .L23
movzbl 9(%rdi), %eax
xorb 9(%rsi), %al
cmpq $10, %r8
movb %al, 9(%rdx)
je .L24
movzbl 10(%rdi), %eax
xorb 10(%rsi), %al
cmpq $11, %r8
movb %al, 10(%rdx)
je .L25
movzbl 11(%rdi), %eax
xorb 11(%rsi), %al
cmpq $12, %r8
movb %al, 11(%rdx)
je .L26
movzbl 12(%rdi), %eax
xorb 12(%rsi), %al
cmpq $13, %r8
movb %al, 12(%rdx)
je .L27
movzbl 13(%rdi), %eax
xorb 13(%rsi), %al
cmpq $14, %r8
movb %al, 13(%rdx)
je .L28
movzbl 14(%rdi), %eax
xorb 14(%rsi), %al
movb %al, 14(%rdx)
movl $15, %eax
.L4:
movq %rcx, %r11
leaq -1(%rcx), %r10
subq %r8, %r11
leaq -16(%r11), %r9
subq %r8, %r10
shrq $4, %r9
addq $1, %r9
movq %r9, %rbx
salq $4, %rbx
cmpq $14, %r10
jbe .L6
leaq (%rdi,%r8), %r13
leaq (%rsi,%r8), %r12
xorl %r10d, %r10d
addq %rdx, %r8
xorl %ebp, %ebp
.L8:
movdqu (%r12,%r10), %xmm0
addq $1, %rbp
pxor 0(%r13,%r10), %xmm0
movups %xmm0, (%r8,%r10)
addq $16, %r10
cmpq %r9, %rbp
jb .L8
addq %rbx, %rax
cmpq %rbx, %r11
je .L1
.L6:
movzbl (%rsi,%rax), %r8d
xorb (%rdi,%rax), %r8b
movb %r8b, (%rdx,%rax)
leaq 1(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 1(%rdi,%rax), %r8d
xorb 1(%rsi,%rax), %r8b
movb %r8b, 1(%rdx,%rax)
leaq 2(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 2(%rdi,%rax), %r8d
xorb 2(%rsi,%rax), %r8b
movb %r8b, 2(%rdx,%rax)
leaq 3(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 3(%rdi,%rax), %r8d
xorb 3(%rsi,%rax), %r8b
movb %r8b, 3(%rdx,%rax)
leaq 4(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 4(%rdi,%rax), %r8d
xorb 4(%rsi,%rax), %r8b
movb %r8b, 4(%rdx,%rax)
leaq 5(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 5(%rdi,%rax), %r8d
xorb 5(%rsi,%rax), %r8b
movb %r8b, 5(%rdx,%rax)
leaq 6(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 6(%rdi,%rax), %r8d
xorb 6(%rsi,%rax), %r8b
movb %r8b, 6(%rdx,%rax)
leaq 7(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 7(%rdi,%rax), %r8d
xorb 7(%rsi,%rax), %r8b
movb %r8b, 7(%rdx,%rax)
leaq 8(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 8(%rdi,%rax), %r8d
xorb 8(%rsi,%rax), %r8b
movb %r8b, 8(%rdx,%rax)
leaq 9(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 9(%rdi,%rax), %r8d
xorb 9(%rsi,%rax), %r8b
movb %r8b, 9(%rdx,%rax)
leaq 10(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 10(%rdi,%rax), %r8d
xorb 10(%rsi,%rax), %r8b
movb %r8b, 10(%rdx,%rax)
leaq 11(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 11(%rdi,%rax), %r8d
xorb 11(%rsi,%rax), %r8b
movb %r8b, 11(%rdx,%rax)
leaq 12(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 12(%rdi,%rax), %r8d
xorb 12(%rsi,%rax), %r8b
movb %r8b, 12(%rdx,%rax)
leaq 13(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 13(%rdi,%rax), %r8d
xorb 13(%rsi,%rax), %r8b
movb %r8b, 13(%rdx,%rax)
leaq 14(%rax), %r8
cmpq %r8, %rcx
jbe .L1
movzbl 14(%rdi,%rax), %ecx
xorb 14(%rsi,%rax), %cl
movb %cl, 14(%rdx,%rax)
.L1:
popq %rbx
popq %rbp
popq %r12
popq %r13
.L38:
rep ret
.L3:
xorl %eax, %eax
.L13:
movzbl (%rdi,%rax), %r8d
xorb (%rsi,%rax), %r8b
movb %r8b, (%rdx,%rax)
addq $1, %rax
cmpq %rax, %rcx
jne .L13
rep ret
.L28:
movl $14, %eax
jmp .L4
.L15:
movl $1, %eax
jmp .L4
.L16:
movl $2, %eax
jmp .L4
.L17:
movl $3, %eax
jmp .L4
.L18:
movl $4, %eax
jmp .L4
.L19:
movl $5, %eax
jmp .L4
.L20:
movl $6, %eax
jmp .L4
.L21:
movl $7, %eax
jmp .L4
.L22:
movl $8, %eax
jmp .L4
.L23:
movl $9, %eax
jmp .L4
.L24:
movl $10, %eax
jmp .L4
.L25:
movl $11, %eax
jmp .L4
.L26:
movl $12, %eax
jmp .L4
.L27:
movl $13, %eax
jmp .L4
如果我们添加-march=native -mtune=native
编译器已经完成了自己的步伐,并且完成了比你正在制作的变体更好的工作。
void f(const char* lhs, const char* rhs, char* out, size_t sz)
{
const int* ilhs = (const int*)lhs;
const int* irhs = (const int*)rhs;
int* iout = (int*)out;
const size_t isz = (sz / sizeof(*ilhs));
const size_t imod = (isz * sizeof(*ilhs));
for (size_t i = 0; i < isz; ++i)
*(iout++) = *(ilhs++) ^ *(irhs)++;
for (size_t i = imod; i < sz; ++i)
out[i] = lhs[i] ^ rhs[i];
}
这会产生almost 400 lines of assembler。
f(char const*, char const*, char*, unsigned long):
movq %rcx, %r8
pushq %r15
pushq %r14
shrq $2, %r8
pushq %r13
pushq %r12
testq %r8, %r8
pushq %rbp
leaq 0(,%r8,4), %rax
pushq %rbx
je .L11
leaq 16(%rsi), %r9
leaq 16(%rdx), %r10
cmpq %r9, %rdx
setnb %r11b
cmpq %r10, %rsi
setnb %r9b
orl %r11d, %r9d
cmpq $8, %r8
seta %r11b
testb %r11b, %r9b
je .L4
leaq 16(%rdi), %r9
cmpq %r9, %rdx
setnb %r11b
cmpq %r10, %rdi
setnb %r9b
orb %r9b, %r11b
je .L4
movq %rdi, %r9
andl $15, %r9d
shrq $2, %r9
negq %r9
andl $3, %r9d
cmpq %r8, %r9
cmova %r8, %r9
testq %r9, %r9
je .L25
movl (%rdi), %r10d
xorl (%rsi), %r10d
cmpq $1, %r9
leaq 4(%rdx), %r13
leaq 4(%rdi), %rbp
leaq 4(%rsi), %rbx
movl %r10d, (%rdx)
movl $1, %r10d
je .L5
movl 4(%rdi), %r10d
xorl 4(%rsi), %r10d
cmpq $2, %r9
leaq 8(%rdx), %r13
leaq 8(%rdi), %rbp
leaq 8(%rsi), %rbx
movl %r10d, 4(%rdx)
movl $2, %r10d
je .L5
movl 8(%rdi), %r10d
xorl 8(%rsi), %r10d
leaq 12(%rdx), %r13
leaq 12(%rdi), %rbp
leaq 12(%rsi), %rbx
movl %r10d, 8(%rdx)
movl $3, %r10d
.L5:
movq %r8, %r15
movq %rax, -16(%rsp)
subq %r9, %r15
salq $2, %r9
leaq -4(%r15), %r11
leaq (%rsi,%r9), %r12
movq %r15, -24(%rsp)
leaq (%rdi,%r9), %r15
addq %rdx, %r9
shrq $2, %r11
movq %r12, -40(%rsp)
movq %r9, -32(%rsp)
addq $1, %r11
xorl %r9d, %r9d
xorl %r12d, %r12d
leaq 0(,%r11,4), %r14
.L8:
movq -40(%rsp), %rax
addq $1, %r12
movdqu (%rax,%r9), %xmm0
movq -32(%rsp), %rax
pxor (%r15,%r9), %xmm0
movups %xmm0, (%rax,%r9)
addq $16, %r9
cmpq %r11, %r12
jb .L8
leaq 0(,%r14,4), %r9
addq %r14, %r10
movq -16(%rsp), %rax
addq %r9, %rbp
addq %r9, %rbx
addq %r9, %r13
cmpq %r14, -24(%rsp)
je .L11
movl 0(%rbp), %r9d
xorl (%rbx), %r9d
movl %r9d, 0(%r13)
leaq 1(%r10), %r9
cmpq %r9, %r8
jbe .L11
movl 4(%rbp), %r9d
xorl 4(%rbx), %r9d
addq $2, %r10
cmpq %r10, %r8
movl %r9d, 4(%r13)
jbe .L11
movl 8(%rbp), %r9d
xorl 8(%rbx), %r9d
movl %r9d, 8(%r13)
.L11:
cmpq %rax, %rcx
jbe .L1
leaq 16(%rax), %r9
leaq (%rsi,%rax), %rbx
movq %rcx, %r11
leaq (%rdx,%rax), %rbp
subq %rax, %r11
leaq (%rdi,%rax), %r10
leaq (%rdx,%r9), %r12
leaq (%rdi,%r9), %r13
cmpq %rbx, %r12
setbe %bl
addq %rsi, %r9
cmpq %r9, %rbp
setnb %r9b
orl %r9d, %ebx
cmpq %r12, %r10
setnb %r12b
cmpq %r13, %rbp
setnb %r9b
orl %r12d, %r9d
testb %r9b, %bl
je .L24
cmpq $19, %r11
jbe .L24
negq %r10
movq %rax, %r9
andl $15, %r10d
cmpq %r11, %r10
cmova %r11, %r10
testq %r10, %r10
je .L15
movzbl (%rdi,%r8,4), %r9d
xorb (%rsi,%r8,4), %r9b
cmpq $1, %r10
movb %r9b, (%rdx,%r8,4)
leaq 1(%rax), %r9
je .L15
movzbl 1(%rdi,%rax), %r8d
leaq 2(%rax), %r9
xorb 1(%rsi,%rax), %r8b
cmpq $2, %r10
movb %r8b, 1(%rdx,%rax)
je .L15
movzbl 2(%rdi,%rax), %r8d
leaq 3(%rax), %r9
xorb 2(%rsi,%rax), %r8b
cmpq $3, %r10
movb %r8b, 2(%rdx,%rax)
je .L15
movzbl 3(%rdi,%rax), %r8d
leaq 4(%rax), %r9
xorb 3(%rsi,%rax), %r8b
cmpq $4, %r10
movb %r8b, 3(%rdx,%rax)
je .L15
movzbl 4(%rdi,%rax), %r8d
leaq 5(%rax), %r9
xorb 4(%rsi,%rax), %r8b
cmpq $5, %r10
movb %r8b, 4(%rdx,%rax)
je .L15
movzbl 5(%rdi,%rax), %r8d
leaq 6(%rax), %r9
xorb 5(%rsi,%rax), %r8b
cmpq $6, %r10
movb %r8b, 5(%rdx,%rax)
je .L15
movzbl 6(%rdi,%rax), %r8d
leaq 7(%rax), %r9
xorb 6(%rsi,%rax), %r8b
cmpq $7, %r10
movb %r8b, 6(%rdx,%rax)
je .L15
movzbl 7(%rdi,%rax), %r8d
leaq 8(%rax), %r9
xorb 7(%rsi,%rax), %r8b
cmpq $8, %r10
movb %r8b, 7(%rdx,%rax)
je .L15
movzbl 8(%rdi,%rax), %r8d
leaq 9(%rax), %r9
xorb 8(%rsi,%rax), %r8b
cmpq $9, %r10
movb %r8b, 8(%rdx,%rax)
je .L15
movzbl 9(%rdi,%rax), %r8d
leaq 10(%rax), %r9
xorb 9(%rsi,%rax), %r8b
cmpq $10, %r10
movb %r8b, 9(%rdx,%rax)
je .L15
movzbl 10(%rdi,%rax), %r8d
leaq 11(%rax), %r9
xorb 10(%rsi,%rax), %r8b
cmpq $11, %r10
movb %r8b, 10(%rdx,%rax)
je .L15
movzbl 11(%rdi,%rax), %r8d
leaq 12(%rax), %r9
xorb 11(%rsi,%rax), %r8b
cmpq $12, %r10
movb %r8b, 11(%rdx,%rax)
je .L15
movzbl 12(%rdi,%rax), %r8d
leaq 13(%rax), %r9
xorb 12(%rsi,%rax), %r8b
cmpq $13, %r10
movb %r8b, 12(%rdx,%rax)
je .L15
movzbl 13(%rdi,%rax), %r8d
leaq 14(%rax), %r9
xorb 13(%rsi,%rax), %r8b
cmpq $14, %r10
movb %r8b, 13(%rdx,%rax)
je .L15
movzbl 14(%rdi,%rax), %r8d
leaq 15(%rax), %r9
xorb 14(%rsi,%rax), %r8b
movb %r8b, 14(%rdx,%rax)
.L15:
movq %r11, %rbp
leaq -1(%r11), %r8
subq %r10, %rbp
leaq -16(%rbp), %rbx
subq %r10, %r8
shrq $4, %rbx
addq $1, %rbx
movq %rbx, %r12
salq $4, %r12
cmpq $14, %r8
jbe .L17
addq %r10, %rax
xorl %r8d, %r8d
xorl %r10d, %r10d
leaq (%rdi,%rax), %r13
leaq (%rsi,%rax), %r11
addq %rdx, %rax
.L19:
movdqu (%r11,%r8), %xmm0
addq $1, %r10
pxor 0(%r13,%r8), %xmm0
movups %xmm0, (%rax,%r8)
addq $16, %r8
cmpq %rbx, %r10
jb .L19
addq %r12, %r9
cmpq %r12, %rbp
je .L1
.L17:
movzbl (%rdi,%r9), %eax
xorb (%rsi,%r9), %al
movb %al, (%rdx,%r9)
leaq 1(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 1(%rdi,%r9), %eax
xorb 1(%rsi,%r9), %al
movb %al, 1(%rdx,%r9)
leaq 2(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 2(%rdi,%r9), %eax
xorb 2(%rsi,%r9), %al
movb %al, 2(%rdx,%r9)
leaq 3(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 3(%rdi,%r9), %eax
xorb 3(%rsi,%r9), %al
movb %al, 3(%rdx,%r9)
leaq 4(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 4(%rdi,%r9), %eax
xorb 4(%rsi,%r9), %al
movb %al, 4(%rdx,%r9)
leaq 5(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 5(%rdi,%r9), %eax
xorb 5(%rsi,%r9), %al
movb %al, 5(%rdx,%r9)
leaq 6(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 6(%rdi,%r9), %eax
xorb 6(%rsi,%r9), %al
movb %al, 6(%rdx,%r9)
leaq 7(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 7(%rdi,%r9), %eax
xorb 7(%rsi,%r9), %al
movb %al, 7(%rdx,%r9)
leaq 8(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 8(%rdi,%r9), %eax
xorb 8(%rsi,%r9), %al
movb %al, 8(%rdx,%r9)
leaq 9(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 9(%rdi,%r9), %eax
xorb 9(%rsi,%r9), %al
movb %al, 9(%rdx,%r9)
leaq 10(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 10(%rdi,%r9), %eax
xorb 10(%rsi,%r9), %al
movb %al, 10(%rdx,%r9)
leaq 11(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 11(%rdi,%r9), %eax
xorb 11(%rsi,%r9), %al
movb %al, 11(%rdx,%r9)
leaq 12(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 12(%rdi,%r9), %eax
xorb 12(%rsi,%r9), %al
movb %al, 12(%rdx,%r9)
leaq 13(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 13(%rdi,%r9), %eax
xorb 13(%rsi,%r9), %al
movb %al, 13(%rdx,%r9)
leaq 14(%r9), %rax
cmpq %rax, %rcx
jbe .L1
movzbl 14(%rdi,%r9), %eax
xorb 14(%rsi,%r9), %al
movb %al, 14(%rdx,%r9)
.L1:
popq %rbx
popq %rbp
popq %r12
popq %r13
popq %r14
popq %r15
ret
.L24:
movzbl (%rdi,%rax), %r8d
xorb (%rsi,%rax), %r8b
movb %r8b, (%rdx,%rax)
addq $1, %rax
cmpq %rax, %rcx
jne .L24
jmp .L1
.L25:
movq %rdx, %r13
movq %rsi, %rbx
movq %rdi, %rbp
xorl %r10d, %r10d
jmp .L5
.L4:
xorl %r9d, %r9d
.L13:
movl (%rdi,%r9,4), %r10d
xorl (%rsi,%r9,4), %r10d
movl %r10d, (%rdx,%r9,4)
addq $1, %r9
cmpq %r9, %r8
jne .L13
jmp .L11
在编译器的简单函数版本中,对sz为零进行了即时且简单的测试:
f(char const*, char const*, char*, unsigned long):
testq %rcx, %rcx
je .L38
在您的版本中,编译器没有意识到您正在尝试跨步,并且代码必须通过许多步骤才能实现:
f(char const*, char const*, char*, unsigned long):
movq %rcx, %r8
pushq %r15
pushq %r14
shrq $2, %r8
pushq %r13
pushq %r12
testq %r8, %r8
pushq %rbp
leaq 0(,%r8,4), %rax
pushq %rbx
je .L11
...
.L11:
cmpq %rax, %rcx
jbe .L1 ...
.L1:
popq %rbx
popq %rbp
popq %r12
popq %r13
popq %r14
popq %r15
ret
我们在这里也有很多注册溢出,跟踪所有这些变量。
让我们比较几个早期的代码块:
编译器:
leaq 16(%rdi), %rax
leaq 16(%rdx), %r9
cmpq %rax, %rdx
setnb %r8b
cmpq %r9, %rdi
setnb %al
orl %eax, %r8d
leaq 16(%rsi), %rax
cmpq %rax, %rdx
setnb %r10b
cmpq %r9, %rsi
setnb %al
orl %r10d, %eax
testb %al, %r8b
je .L3
cmpq $19, %rcx
jbe .L3
movq %rdi, %r8
pushq %r13
pushq %r12
negq %r8
pushq %rbp
pushq %rbx
andl $15, %r8d
cmpq %rcx, %r8
cmova %rcx, %r8
xorl %eax, %eax
testq %r8, %r8
je .L4
此致:
leaq 16(%rsi), %r9
leaq 16(%rdx), %r10
cmpq %r9, %rdx
setnb %r11b
cmpq %r10, %rsi
setnb %r9b
orl %r11d, %r9d
cmpq $8, %r8
seta %r11b
testb %r11b, %r9b
je .L4
leaq 16(%rdi), %r9
cmpq %r9, %rdx
setnb %r11b
cmpq %r10, %rdi
setnb %r9b
orb %r9b, %r11b
je .L4
movq %rdi, %r9
andl $15, %r9d
shrq $2, %r9
negq %r9
andl $3, %r9d
cmpq %r8, %r9
cmova %r8, %r9
testq %r9, %r9
je .L25
我们在这里可以看到,编译器只需要为每个操作发出比原始版本本身更多的指令。