while (condition) {
...
}
ワークフロー:
- 状態を確認してください。
- false の場合、ループの外側にジャンプします。
- 1回の反復を実行します。
- トップにジャンプします。
if (condition) do {
...
} while (condition);
ワークフロー:
- 状態を確認してください。
- false の場合、ループを超えてジャンプします。
- 1回の反復を実行します。
- 状態を確認してください。
- true の場合、ステップ 3 にジャンプします。
これら 2 つを比較すると、ループのステップが 1 つだけで、一般にジャンプの数が反復の数よりも 1 つ少ない場合、後者はまったくジャンプしない可能性があることが簡単にわかります。前者は条件をチェックするためにジャンプして戻る必要があり、条件が false の場合にのみループから飛び出します。
最新のパイプライン化された CPU アーキテクチャでのジャンプは、非常にコストがかかる可能性があります。CPU はジャンプ前にチェックの実行を終了しているため、そのジャンプ以降の命令は既にパイプラインの途中にあります。分岐予測が失敗した場合、この処理はすべて破棄する必要があります。パイプラインが再準備されている間、それ以上の実行は遅れます。
前述の分岐予測の説明: 条件付きジャンプの種類ごとに、CPU には2 つの命令があり、それぞれに結果への賭けが含まれます。たとえば、最後の反復を除くすべての反復でジャンプを行う必要があるため、「ゼロでない場合はジャンプ、ゼロでないことに賭ける」という命令をループの最後に配置します。こうすることで、CPU は、ジャンプ命令自体に続く命令ではなく、ジャンプ ターゲットに続く命令でパイプラインのポンピングを開始します。
重要な注意点
これを、ソース コード レベルで最適化する方法の例として取り上げないでください。あなたの質問からすでに明らかなように、最初の形式から2番目の形式への変換は、JITコンパイラがルーチンの問題として完全に独自に行うものであるため、それは完全に見当違いです。