编译器涉嫌优化while循环

时间:2015-07-12 12:36:51

标签: c performance assembly while-loop

在嵌入式编程讲座的this部分,Samek博士解释了编译器如何能够实现“原始代码”的效率(可能是由于这意味着由语法的逻辑顺序决定的实现) ):

  

我希望你注意到了   反汇编代码实现了不同的控制流   我为while循环描述的内容。假设原始代码   首先测试条件,然后跳过循环体,如果   条件不正确。编译后的代码以无条件开头   分支并反转循环体的顺序和测试   条件。但是,当你想到它时,那两个控制流程   是相同的,除了生成的更快,因为它只有   循环底部的一个条件分支。

在他的解释中,他参考了所示的两个流程图。描述编译代码的图表说明了“它在循环底部只有一个条件分支”。我似乎无法看到它在实践中如何运作:

  • Here是我拍摄的一个屏幕截图,展示了如何实现原始代码。 (初始)机器指令的顺序:

0x2815 CMP - > 0x1c40 ADDS - > repeat until condition is false

  • Here是另一个屏幕截图,显示编译器使用的序列。 (初始)机器指令的顺序:

0x2815 CMP - > 0xdbfc BLT.N - > 0x1c40 ADDS - > repeat until condition is false

我可以理解两个控制流是如何相等的(至少从图中看是如此),但肯定生成的(右边)如何更快。首先,两个图表最开始的箭头导致了相同的分支。其次,虽然分支似乎确实发生在右侧的原理图中,正如您从屏幕截图中看到的那样,模拟器似乎表明两个方法都是从机器指令开始的。比较(0x2815 CMP)。

如何协调流程图与我在实践中看到的内容?

2 个答案:

答案 0 :(得分:6)

我同意Kerren SB的回答。我将更详细地讨论它:

原始逻辑具有以下在每次迭代期间执行的跳转指令:

begin_loop:
    cmp counter, 21
    jge end_loop           ; jump when greater or equal
    ...
    jmp begin_loop
end_loop:
    ....

修订后的逻辑在每次迭代期间执行的指令减少一个:

    jmp test_loop          ; executed once; not part of loop
begin_loop:
    ...
test_loop:
    cmp counter, 21
    jlt begin_loop         ; jump when less than
    ...

因此在循环中保存了无条件jmp begin_loop

答案 1 :(得分:5)

重要的唯一指令是在每个循环中重复的指令。重新排列逻辑的重点是每轮循环只有一个跳。在整个循环之前和之后可能会有几次跳跃,但我们并不关心这些。唯一昂贵的是那些一遍又一遍地完成的事情。