为什么底部测试循环更可取?

时间:2012-03-20 00:02:12

标签: gcc assembly compiler-construction x86 llvm

我听说过有人说编译器经常将循环条件移到循环的底部。也就是说,像这样的循环:

while (condition) {
    ...
}

更改为:

if (condition) {
     do {
         ...
     } while (condition);
}

关于机器无关优化,为什么后者更可取?

3 个答案:

答案 0 :(得分:7)

如果没有编译器优化,第一个循环将转到汇编代码,如下所示:

  @@:
cmp ... ; or test ...
jz @f

...
jmp @b

而第二个循环是这样的:

jmp bottom

  @@:
...

  bottom:
cmp ... ; or test ...
jz @b

通常会预测会进行条件跳转,因此第一种方法可能会导致更多的管道/指令缓存刷新。

然而,最重要的是,对于第一个循环,每个循环迭代(2N)有两个分支可用,而在第二个循环中,每个循环迭代只有一个具有固定开销的分支第一次无条件跳转(N+1)。

有关循环优化的详细信息,请参阅此assembly optimisation guide的第88页。

答案 1 :(得分:0)

你有些错误。典型的优化是:

    jmp $test;
$loop:
    ; loop statements
$test:
    test <condition>;
    branch-true $loop;

而不是:

$loop:
    test <condition>;
    branch-false $end;
    ; loop statements
    branch loop;
$end:

在循环的每次迭代中都有两个分支。另一个优点是初始跳转后的部分与为do/while生成的代码相同。

答案 2 :(得分:0)

对于汇编视图,循环只是一个跳转代码的跳转指令。因此编译器需要在循环结束时插入一个跳转。

许多指令集,如x86,ARM,MIPS都提供条件跳转/分支指令。是否根据指令中指定的条件进行跳转。

因此编译器更喜欢这种指令,并将条件移动到循环的末尾以使用该指令。