64位架构优化

时间:2016-09-27 15:26:27

标签: c++ c performance 32bit-64bit

我正在测试一个计算两个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;问题,但操作系统或类似的东西。目前我还没有想到这一点。

1 个答案:

答案 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

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