1

LLVM 用の LDC D コンパイラは、ターゲットが静的に認識されていることを証明できる場合、状況によっては間接関数呼び出しをインライン化できます。これが発生する可能性がある場所のおもちゃの例 (D) を次に示します。

void main() {
    uint num;

    void incNum() {
        num++;
    }

    auto myDelegate = &incNum;
    myDelegate();
}

この場合、myDelegate()呼び出しは名目上は間接呼び出しですが、対象は人間の読者と LLVM/LDC のフロー分析にとって明らかであるため、インライン化されます。

最新のコンパイラで静的に認識可能なターゲットへの間接関数呼び出しをインライン化する機能は、どの程度普及していますか? これを実行できる事前コンパイラは LLVM だけですか? JITコンパイラではより一般的ですか?

4

2 に答える 2

1

ほとんどのC++コンパイラがこの種の最適化を行ったとしても、少なくともいくつかのバリエーションはありますが、驚くことではありません。これは、実際には非常に言語およびコンパイラに固有です。

D言語について話すことはできませんが、C / C ++の場合、上記のこの種の最適化は、ポインター演算のために行うのが難しい場合があります。たとえば、代わりにこのようなコードの場合、コードを最適化できますか?

++myDelegate;
myDelegate();

の種類に大きく依存しmyDelegateます。上記は有効なC/C ++である可能性がありますが、myDelegate()のインライン化は、コンパイラーが保証できるものではない可能性があります。

他の言語(Java、C#など)にはポインター演算がないため、より多くの仮定を行うことができます。たとえば、Sun JVMは、間接的な多態的な呼び出しを直接呼び出しに変換できます。これは非常に優れています、IMHO。例:

   public class A2 {
      private final B2 b;
      public A2(B2 b) {
        this.b = b;
      }
      public void run() {
        b.f();
      }
    }

    public interface B2 {
      public void f();
    }

    public class C2 implements B2 {
      public void f() {
      }
    }

A2 a2 = new A2(new C2());実際に最適化することができ、SunJVMはそれを取得できます。

この例は、Javaスペシャリストのニュースレター157から入手したもので、この種のWRTJavaについて学ぶために読むことをお勧めします。

于 2010-08-23T13:10:09.720 に答える
0

コンパイルを最適化するのに最も適しているのは、そのようなことを実行できると思います(とにかく、あらゆる種類のフロー分析を実行することを考慮して)。

Jitコンパイラーは、さらに一歩進んで、ターゲットが静的に認識されている(または単に認識されていない)ことを証明できないインライン間接呼び出しを実行することもできます。その場合、関数呼び出しの前にターゲットが期待されるものであるかどうかのテストを挿入し、そうでない場合にのみ間接呼び出しを使用します(各パスが取得された頻度に応じてrejitします)。IIRC .Net Jitがこれを行い、Javaもそうすると思います。

于 2010-09-28T21:03:52.573 に答える