64位架构优化

64 bits architecture optimization

本文关键字:优化 64位      更新时间:2023-10-16

我正在测试一个计算两个字符缓冲区的异或的函数。为了提高速度,我正在检查使用整数指针(32位)和长整数指针(64位)的速度。我使用一个char指针作为参考的函数。当然,我是在64位机器上测试的。

但是我没有得到我期望的结果。最后我试着用这三个函数。当我比较"XOR_Diff_Char"answers"XOR_Diff_Int"时,我得到了大约3倍的速度提高,因为函数"_Int"在主"for"中迭代次数少了4倍。但是当我比较"XOR_Diff_Int"answers"XOR_Diff_QWORD"时,改进大约是5-10%,比我预期的要慢,因为主"for"在"_QWORD"中的迭代次数比在"_Int"中的迭代次数少2倍。我曾尝试(为了比较速度)在- 0和-O3之间使用不同的标志进行编译,但我没有发现任何差异。

我在Debian 64位下使用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的一半,所以速度应该是两倍(尽管函数的开销等等)。所以我不太理解为什么这两种情况下的速度是相似的。对于测试,我只使用像

这样简单的东西
gettimeofday(&t1, NULL);
count = XOR_Diff_Int(pDataIn, prevData, pOut, SIZE);
gettimeofday(&t2, NULL);

将"_Int"改为"_QWORD",并为两种类型的测试重新编译。

编辑2:

我不太了解汇编程序,但我比较了两个函数(主要的"for"),我得到了这个:

// 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

所以我理解64位的情况更快,因为使用8字节的指令。我认为这不是"指令"的问题,而是操作系统之类的问题。目前我对这件事没有任何想法。

看来你想做的是比编译器更聪明。编译器赢了。

给定如下简单函数:

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编译,编译器吐出近300行汇编程序:

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];
}

这产生了将近400行汇编程序。

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

我们可以在这里看到,编译器必须为每个操作发出比原始版本更多的指令。