C编译器输出中的冗余移动

时间:2016-03-06 15:28:28

标签: c assembly x86 clang

以下练习来自CSAPP 3.21:

int loop_while(int a, int b)
{
    int result = 1;
    while (a < b)
    {
        result *= (a+b);
        a++;
    }
    return result;
}

gcc生成以下汇编代码:

  ;a at %ebp+8, b at %ebp+12
    movl 8(%ebp), %ecx
    movl 12(%ebp), %ebx
    movl $1, %eax          ; this one
    cmpl %ebx, %ecx
    jge .L11
    leal (%ebx,%ecx), %edx
    movl $1, %eax          ; and this one
.L12:
    imull %edx, %eax
    addl $1, %ecx
    addl $1, %edx
    cmpl %ecx, %ebx
    jg .L12
.L11: ......

我对第3行和第7行的movl $1, %eax感到困惑:{4}中没有修改%eax

cmpl %ebx, %ecx
jge .L11
leal (%ebx,%ecx), %edx

不需要再次movl

我尝试使用x86_64-apple-darwin15.3.0

gcc 4.2.1上生成汇编代码
    movl    $1, %eax
    cmpl    %esi, %edi
    jge LBB0_2
    .align  4, 0x90
LBB0_1:

    leal    (%rsi,%rdi), %ecx
    imull   %ecx, %eax
    incl    %edi
    cmpl    %edi, %esi
    jne LBB0_1
LBB0_2:
    popq    %rbp
    retq
    .cfi_endproc

无法找到重复movl的等效说明。

写第二个movl $1, %eax的重点是什么?

1 个答案:

答案 0 :(得分:1)

自OS X 10.8起,Apple已将gcc符号链接到clang,因此第一个代码实际上是由clang生成的。

My Clang 3.7.1 generates代码相同,即使-O2-O3也是如此。正如您所注意到的那样,第二个movl毫无意义。

如果您可以使用当前位于inform的版本重现它,则可能需要trunk LLVM / Clang团队。