与其他类型的循环相比,编译器是否为 do-while 循环生成了更好的代码? [英] Do compilers produce better code for do-while loops versus other types of loops?

查看:10
本文介绍了与其他类型的循环相比,编译器是否为 do-while 循环生成了更好的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

zlib 压缩库(在许多其他项目中使用 Chromium 项目)中有一条评论暗示 C 中的 do-while 循环会生成更好的";大多数编译器上的代码.这是它出现的代码片段.

There's a comment in the zlib compression library (which is used in the Chromium project among many others) which implies that a do-while loop in C generates "better" code on most compilers. Here is the snippet of code where it appears.

do {
} while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
         *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
         *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
         *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
         scan < strend);
/* The funny "do {}" generates better code on most compilers */

https://code.google.com/p/chromium/codesearch#chromium/src/third_party/zlib/deflate.c&l=1225

是否有任何证据表明大多数(或任何)编译器会生成更好(例如更高效)的代码?

Is there any evidence that most (or any) compilers would generate better (e.g. more efficient) code?

更新: Mark Adler,原作者之一,在评论中提供了一些背景信息.

推荐答案

首先:

do-while 循环与 while-loop 或 for-loop 不同.

A do-while loop is not the same as a while-loop or a for-loop.

  • whilefor 循环可能根本不运行循环体.
  • do-while 循环总是至少运行循环体一次 - 它会跳过初始条件检查.
  • while and for loops may not run the loop body at all.
  • A do-while loop always runs the loop body at least once - it skips the initial condition check.

这就是逻辑上的区别.也就是说,并不是每个人都严格遵守这一点.使用 whilefor 循环是很常见的,即使它保证总是循环至少一次.(特别是在具有 foreach 循环的语言中.)

So that's the logical difference. That said, not everyone strictly adheres to this. It is quite common for while or for loops to be used even when it is guaranteed that it will always loop at least once. (Especially in languages with foreach loops.)

因此,为了避免比较苹果和橙子,我将继续假设循环将始终至少运行一次.此外,我不会再次提及 for 循环,因为它们本质上是 while 循环,带有一些用于循环计数器的语法糖.

So to avoid comparing apples and oranges, I'll proceed assuming that the loop will always run at least once. Furthermore, I won't mention for loops again since they are essentially while loops with a bit of syntax sugar for a loop counter.

所以我会回答这个问题:

So I'll be answering the question:

如果保证 while 循环至少循环一次,那么使用 do-while 循环是否有任何性能提升.

If a while loop is guaranteed to loop at least once, is there any performance gain from using a do-while loop instead.

do-while 会跳过第一个条件检查.所以要评估的分支少了一个,条件也少了一个.

A do-while skips the first condition check. So there is one less branch and one less condition to evaluate.

如果检查条件的成本很高,并且您知道可以保证至少循环一次,那么 do-while 循环可能会更快.

If the condition is expensive to check, and you know you're guaranteed to loop at least once, then a do-while loop could be faster.

虽然这充其量被认为是一种微优化,但编译器不能总是这样做:特别是当编译器无法证明循环总是至少进入一次时.

And while this is considered a micro-optimization at best, it is one that the compiler can't always do: Specifically when the compiler is unable to prove that the loop will always enter at least once.

换句话说,一个while循环:

In other words, a while-loop:

while (condition){
    body
}

实际上与此相同:

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

如果你知道你总是会循环至少一次,那么这个 if 语句就是多余的.

If you know that you will always loop at least once, that if-statement is extraneous.

同样在汇编级别,这大致是不同循环编译成的方式:

Likewise at the assembly level, this is roughly how the different loops compile to:

do-while 循环:

start:
    body
    test
    conditional jump to start

while 循环:

    test
    conditional jump to end
start:
    body
    test
    conditional jump to start
end:

请注意,条件已重复.另一种方法是:

Note that the condition has been duplicated. An alternate approach is:

    unconditional jump to end
start:
    body
end:
    test
    conditional jump to start

...用重复的代码换取额外的跳转.

... which trades away the duplicate code for an additional jump.

不管怎样,它仍然比普通的 do-while 循环更糟糕.

Either way, it's still worse than a normal do-while loop.

也就是说,编译器可以做他们想做的事.如果他们能证明循环总是进入一次,那么它已经为你完成了工作.

That said, compilers can do what they want. And if they can prove that the loop always enters once, then it has done the work for you.

但是对于问题中的特定示例来说,事情有点奇怪,因为它有一个空的循环体.由于没有正文,所以 whiledo-while 之间没有逻辑上的区别.

But things are bit weird for the particular example in the question because it has an empty loop body. Since there is no body, there's no logical difference between while and do-while.

FWIW,我在 Visual Studio 2012 中对此进行了测试:

FWIW, I tested this in Visual Studio 2012:

  • 对于空体,它确实为 whiledo-while 生成相同的代码.因此,这部分很可能是编译器不那么出色的旧时代的残余.

  • With the empty body, it does actually generate the same code for while and do-while. So that part is likely a remnant of the old days when compilers weren't as great.

但是,VS2012 使用非空主体,设法避免条件代码的重复,但仍会产生额外的条件跳转.

But with a non-empty body, VS2012 manages to avoid duplication of the condition code, but still generates an extra conditional jump.

因此具有讽刺意味的是,虽然问题中的示例强调了为什么 do-while 循环在一般情况下可能更快,但该示例本身似乎对现代编译器没有任何好处.

So it's ironic that while the example in the question highlights why a do-while loop could be faster in the general case, the example itself doesn't seem to give any benefit on a modern compiler.

考虑到评论的年龄,我们只能猜测它为何重要.当时的编译器很可能无法识别主体是空的.(或者如果他们这样做了,他们就没有使用这些信息.)

Considering how old the comment was, we can only guess at why it would matter. It's very possible that the compilers at the time weren't capable of recognizing that the body was empty. (Or if they did, they didn't use the information.)

这篇关于与其他类型的循环相比,编译器是否为 do-while 循环生成了更好的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆