繁体   English   中英

关于gcc翻译的汇编代码为C实现N阶乘的疑惑

[英]Doubts about assembly code translated by gcc for implementation of N factorial by C

我对阶乘函数的反汇编感到困惑。

代码

long factorial(int x)
{
    long result = 1;

    while (x > 1)
    {
        result = result * x;
        x= x - 1;
    }

    return result;
}

我使用 gcc 命令反汇编阶乘函数gcc -S -O1 test.c

factorial:
.LFB0:
        cmpl    $1, %edi
        jle     .L2
        movslq  %edi, %rdx
        leaq    -1(%rdx), %rcx
        leal    -2(%rdi), %eax
        subq    %rax, %rcx
        movl    $1, %eax
.L3:
        imulq   %rdx, %rax
        subq    $1, %rdx
        cmpq    %rcx, %rdx
        jne     .L3
.L2:
        movl    $1, %eax
        rep ret

我不明白下面的代码是做什么的,有人可以帮助我吗?

movq    %rax, %rdx
leaq    -1(%rax), %rcx
leal    -2(%rdi), %esi
subq    %rsi, %rcx

(对问题的更新更改了 C 和 asm,删除了问题仍然询问的movq %rax, %rdx ,但否则会使答案的第一部分无效。请参阅编辑历史记录或遵循此答案中的 Godbolt 链接请参阅本节所指的内容。)

movq %rax, %rdx正在制作符号扩展x (32 位int到 64 位long )的副本,用于在表达式result * x隐式执行(long)x表达式的循环中。 请注意,它避免了每次循环都像 C 抽象机那样重做符号扩展。 (与 GCC5 及更早版本不同,它们或多或少地按照编写的方式编译,只有像 do{}while 循环结构这样的普通转换。)

它以符号扩展x 2 个副本开始的事实是因为您的 C 以result=x开头。 这是您的阶乘实现中的一个错误,因为您没有执行x-- ,但编译器只是在实现您编写的内容。 实际上使用x--会生成其他奇怪的代码( https://godbolt.org/z/345K6hbas ),例如leal -3(%rdi), %edi / addq $1, %rdi仅与lea -2(%rdi), %edi以防 LEA 产生 0xFFFFFFFF (-1) 并且 qword +1 进入高 32 位。 但这不可能发生,因为较早的 cmp/jcc 会提前返回x-1 <= 1 ,因此 rdi-3+1 是另一个错过的优化。


其他 3 条指令(lea/lea/sub)是 GCC 是愚蠢的,我认为以复杂的方式计算常量1作为 RCX 中的循环终止条件,以与 RDX 进行比较。 这是一个遗漏的优化错误,您可以报告GCC 的 bugzilla,因为它仍然发生在 -O2 ( https://godbolt.org/z/achGeePYb ) 的当前主干夜间构建中。

我猜测提升符号扩展导致创建此逻辑为时已晚,优化传递无法将其分类为合理的东西,或者以他们不能/不可以的方式。


顺便说一句,这看起来像 GCC7,因为它与您的 asm https://godbolt.org/z/jMhjsvfdM匹配。 后来的 GCC 省略了 rep 前缀(但否则会造成同样的混乱),早期的 GCC 要么使 asm 略有不同,要么(gcc5 及更早版本)直接进入循环而没有先做那么多。 但是他们每次循环迭代都会重做x符号扩展(从 32 位int到 64 位long )。

即使在-O2也会发生这种情况,因此这不是仅启用部分优化 (-O1) 的结果。 GCC8 和更早的在-O3处自动矢量化,但这可能没有利润,这可能是 GCC9 和后来停止这样做的原因。 (x86 在 AVX-512 之前没有 SIMD qword 乘法, -march=skylake-avx512 ,并且从多个pmuludq操作中合成它很慢)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM