2016-04-05 18 views
5

私は.Netネイティブコンパイラによって実行される最適化技術に取り組んでいます。 私は、サンプルループ作成しました:.Netネイティブコンパイルループが逆の順序であるのはなぜですか?

 for (int i = 0; i < 100; i++) 
     { 
      Function(); 
     } 

をそして私はネイティブでそれをまとめました。それから、IDAにある.dllのファイルをマシンコードで解体しました。その結果、私が持っている:

enter image description here

(私はいくつかの不要な行を削除したので、そのアドレスラインがinconsistantです心配しないでください)

私は、add esi, 0FFFFFFFFhは本当にsubtract one from esi and alter Zero Flag if neededを意味することを理解しますまだゼロに達していなければ、最初にジャンプすることができます。

私は理解していないことは、なぜコンパイラはループを反省したのですか?

私は

LOOP: 
add esi, 0FFFFFFFFh 
jnz LOOP 

はただ速い例えばより

LOOP: 
inc esi 
cmp esi, 064h 
jl LOOP 

である。しかし、それはそのため実際にあると、本当に大きな速度差であるという結論に来ましたの?

+0

即時値を持つADDはINCより高速です。また、これらのすべてを3行のコードでスキップします。次に、違いは本当に重要です(サイズとスピードの両方)。現実世界のプログラムで約30000の場所でこれを行うとしたら... –

+0

これは高速で一般的なオプティマイザは、プログラムのセマンティクスを変更することなくコードを高速化するあらゆる最適化を適用します。 –

+0

逆方向に関しては、おそらくゼロとの比較が特定の値との比較よりも速いでしょうか? – user5226582

答えて

3

inc might be slower than add because of the partial flag update。さらにaddはゼロフラグに影響しますので、別のcmp命令を使用する必要はありません。ちょうど直接ジャンプします。

これは、loop optimization

反転の一つの有名なタイプである:ループ反転は値がインデックス変数に割り当てられる順序を逆転させます。これは、依存関係をなくして他の最適化を可能にする微妙な最適化です。また、特定のアーキテクチャでは、単一方向のみにカウントされるアセンブリ言語レベル(例えば、減分ジャンプ、ゼロでなければならない(DJNZ))でループ構造を利用する。

あなたは他のコンパイラhereために結果を見ることができます。

+0

' inc'は遅く、1クロックサイクルで 'add'します。 [インテル®64およびIA-32アーキテクチャー最適化リファレンス・マニュアル](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures- optimization-manual.html)付録Cまでスクロールすると、各x86/x6の待ち時間とスループット時間がわかります4命令。 1クロックサイクルは重要ではないように見えるかもしれませんが、数百または数千のループがある場合は、高速になります。 – Icemanind

1

あなたの結論が正しい:Addは条件分岐で使用ゼロフラグを設定するように反転サイクルは、(レジスタ値が0に達したときのサイクル意志が終了する)0を標的とします。

このようにすれば、Cmp専用のものは必要ありません。サイズの最適化2)コンパイラプログラマーの決定と他のanswerの結論も高速です。

これは、ループターゲティング0を書くための非常に一般的なアセンブラトリックです。私はあなたがアセンブラを理解していることに驚いていますが、それについて知らない(尋ねる)ことはありません。

関連する問題