私は、.NET プラットフォームを対象とするプログラミング言語を作成することを計画しており、そのようなプラットフォームを対象とするコード生成の側面について考え始めました。私はコンパイラを書くのは初めてですが、コンパイルのフェーズの1つとして最適化が行われていることを知っています(または存在する可能性があります)。JITコンパイラーやJVMのHotSpotなどは実行時に最適化できるため、出力の最適化に時間を費やすことの利点について疑問に思い始めました(この場合はCILですが、これはJVMにも当てはまります)。JIT は既に最適化されているため、.NET または JVM を対象とする場合、生成されたコード (CIL または同等の JVM) を最適化するメリットはありますか?
3 に答える
場合によります。無数の最適化があります。特定のコンパイラ (使用するコンパイラ、JIT コンパイラ、またはその他のコンパイラ) は、必ずそれらのサブセットのみを実装します。この選択は、利用可能な時間、一般的/予想される入力コード、優先度などに依存します。したがって、JIT コンパイラを構築したエンジニアは、期待していたプログラムではうまく機能する最適化を選択した可能性がありますが、プログラムの種類ではうまく機能しませんでした。気にする。
JIT コンパイラーが見逃している最適化を特定する必要があります。もちろん、これを行う方法は経験に基づいています。実際にプログラムを作成し、JIT コンパイラーに最適化させます (この部分を適切に実行してください。デバッグを無効にし、リリース用にコンパイルし、現実的なベンチマークを選択するなど)。最終マシンコード。予期しないコードを探し (もちろん、これにはアセンブリの知識が必要です)、それが最適化されていないかどうか、または JIT が思ったよりもスマートであったかどうかを判断します。
最適化に失敗した場合は、別の問題があります。必要なマシン コードを出力できず、代わりに別の IL を生成する必要があります。最適化されていないのは、おそらくVM が認識していない言語機能 (JVM のマルチメソッドなど) が原因です。コンパイル中にそれを VM の用語に落とし込みましたが、選択した翻訳は JIT のパスの順序、ヒューリスティックなどにうまく適合しません。マシン コードを自分で出力することはできないため、代わりの IL フラグメントを見つける必要があります。同じ入力言語コード。理想的には、JIT コンパイラーが適切に処理できるものです。それを見つけるのは想像力の試練かもしれませんが、技術的に難しいわけではなく、ベンチマークと組み合わせた当て推量にすぎません。
別の回答が指摘しているように、JIT コンパイラーは時間の制約の下で動作します。これにより、最適化が見逃される可能性があります (たとえば、定数の伝播が時間切れになるなど) が、JIT コンパイラの作成者が同じ問題に直面したため、より大きな/より多くのものを作成しない場合、これはおそらくそれほど深刻ではありません。複雑なコード。 JIT コンパイラーがすべてを修正できないほど悪いコードを作成した場合は、AOT コンパイラーでその最適化を複製する必要があります。ただし、これがありそうなシナリオであるとは確信していません。たとえそれが起こったとしても、非常に単純な最適化でさえ問題をほとんど解決するはずです.
つまり、要約すると、簡単な変換から始めて、最適化の失敗を探し出し、JIT コンパイラーの最適化を容易にするか、自分で実行します (可能であれば、AOT 設定では適応最適化ははるかに困難です)。
この質問は一般的に答えにくいと思います。
たとえば、F# コンパイラは末尾呼び出しの最適化を実行します。その言語では末尾再帰関数を使用するのが一般的であるため、F# コンパイラは、場合によっては JIT コンパイラよりも最適化を行うことができ、JIT コンパイラの一部のバージョンでは実行されません。最適化をまったく実行しません。
したがって、あなたの言語には、単純な実装ではうまく機能しない一般的な操作が含まれている可能性があります。その場合、最適化された IL コードを発行することは理にかなっています。
あなたがすべきことは、通常のプログラムを書くときと同じだと思います。まず、単純で読みやすい方法でコードを書きます。何かがうまく機能しない場合にのみ、それを最適化してください。将来、何らかの最適化が必要になる可能性があることを考慮して、最適化のためにコードの半分を書き直す必要がないように、コードを十分にモジュール化することを検討する価値があります。しかし、今のところ、それで十分なはずです。
コンパイラを書くことは、すでに十分に困難な仕事です (IL をターゲットにしている場合でも)。最初にそれを終えて、後で最適化について考えてください。
一般に、JIT コンパイラーには、実行しようとする最適化の量を制御するいくつかのしきい値があります。これらは、メソッドの IL のサイズおよび/またはメソッドの JIT コンパイルに既に費やされた時間に基づいている場合があります。そうです、すでに最適化されている IL は、さらなる JIT 最適化の恩恵を受ける可能性があります。いつものように、トレードオフがあります: AOT 最適化をコンパイラに追加する (およびそれらをテスト/維持する) のにどれくらいの時間を費やしたいか、どのくらいの時間でコードを JIT コンパイルできるか、およびどのレベルの最適化を使用するかです。
改善の程度は、AOT 最適化された IL が最適化されていない IL と比較してどれだけ単純 (かつ小さい) か、および JIT コンパイラを管理するしきい値 (少なくとも Microsoft CLR については広く知られていない) に大きく依存します。 )。確認する唯一の方法は、自分でテストを行うことです。