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

I wouldn't be surprised if most C++ compilers did this kind of optimization, at least some variations of it. This is very language- and compiler-specific, actually.

I can't speak for the D language, but for C/C++, this kind of optimization above can be difficult to make because of pointer arithmetic. e.g., can you optimize the code if it's something like this instead?

++myDelegate;
myDelegate();

It depends so heavily on the type of myDelegate. The above can be valid C/C++, but inlining myDelegate() might not be something the compiler can guarantee.

Other languages (e.g., Java, C#, etc.) don't have pointer arithmetic, so more assumptions can be made. The Sun JVM, for example, can convert indirect, polymorphic calls to direct calls, which is pretty cool, IMHO. Example:

   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()); can actually be optimized, and the Sun JVM can pick that up.

I got this example from the Java Specialists newletter 157, which I recommend reading to learn about this kind of thing WRT Java.

于 2010-08-23T13:10:09.720 回答
0

我会假设大多数优化编译都可以做类似的事情(考虑到他们无论如何都会做各种流分析)。

Jit 编译器有时甚至可以更进一步,内联间接调用,它们无法证明目标是静态已知的(或根本不知道的)。对于这种情况,如果目标是函数调用之前的预期目标,他们会插入一个测试,并且仅在不是时才使用间接调用(并根据每条路径的使用频率重新调整)。IIRC .Net Jit 会这样做,我认为 java 也会这样做。

于 2010-09-28T21:03:52.573 回答