我听说过有人说编译器经常将循环条件移到循环的底部。也就是说,像这样的循环:
while (condition) {
...
}
更改为:
if (condition) {
do {
...
} while (condition);
}
关于机器无关优化,为什么后者更可取?
答案 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都提供条件跳转/分支指令。是否根据指令中指定的条件进行跳转。
因此编译器更喜欢这种指令,并将条件移动到循环的末尾以使用该指令。