views:

46

answers:

2

The LDC D compiler for LLVM can inline indirect function calls under some circumstances if it can prove that the target is statically known. Here's a toy example (in D) of where this might happen:

void main() {
    uint num;

    void incNum() {
        num++;
    }

    auto myDelegate = &incNum;
    myDelegate();
}

In this case, even though the myDelegate() call is nominally an indirect call, the target is obvious to a human reader and to LLVM/LDC's flow analysis, so it gets inlined.

How widespread a feature is the ability to inline indirect function calls to statically knowable targets in modern compilers? Is LLVM the only one ahead-of-time compiler that can do this? Is it more common with JIT compilers?

+1  A: 

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.

The Alchemist
A: 

I would assume that most well optimizing compiles can do something like that (considering they do all kinds of flow analysis anyhow).

Jit compilers can sometimes even go a step further and inline indirect calls for which they can't prove that the target is statically known (or where it simply isn't). For that case they insert a test if the target is the expected one before the function call and use the indirect call only if it isn't (and rejit depending on how often each path was taken). IIRC the .Net Jit does this and I would assume java does so too.

Grizzly