Какие компиляторы могут включать косвенные вызовы функций? - PullRequest
1 голос
/ 22 августа 2010

Компилятор LDC D для LLVM может при некоторых обстоятельствах включать косвенные вызовы функций, если он может доказать, что цель статически известна.Вот игрушечный пример (в D) того, где это может произойти:

void main() {
    uint num;

    void incNum() {
        num++;
    }

    auto myDelegate = &incNum;
    myDelegate();
}

В этом случае, хотя вызов myDelegate() номинально является косвенным вызовом, цель очевидна для читателя и человека.Анализ потоков LLVM / LDC, поэтому он становится встроенным.

Насколько широко распространена возможность встроенных косвенных вызовов функций для статически узнаваемых целей в современных компиляторах?Является ли LLVM единственным опережающим компилятором, который может это сделать?Это чаще встречается в JIT-компиляторах?

Ответы [ 2 ]

1 голос
/ 23 августа 2010

Я не удивлюсь, если большинство компиляторов C ++ выполнят такую ​​оптимизацию, по крайней мере, некоторые ее варианты.На самом деле это очень зависит от языка и компилятора.

Я не могу говорить для языка D, но для C / C ++ вышеописанный тип оптимизации может быть сложным из-за арифметики указателей.Например, можете ли вы оптимизировать код, если он похож на этот?

++myDelegate;
myDelegate();

Это так сильно зависит от типа myDelegate.Вышеприведенное может быть допустимым C / C ++, но встраивание myDelegate () может быть не тем, что может гарантировать компилятор.

Другие языки (например, Java, C # и т. Д.) Не имеют арифметику указателей, поэтому болеепредположения могут быть сделаны.Например, Sun JVM может преобразовывать косвенные полиморфные вызовы в прямые, что довольно круто, ИМХО.Пример:

   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()); действительно может быть оптимизирован, и Sun JVM может это подхватить.

Я получил этот пример из новостной рассылки Java Specialists 157 , который я рекомендую прочитать, чтобы узнать о таких вещах WRT Java.

0 голосов
/ 29 сентября 2010

Я бы предположил, что большинство хорошо оптимизирующих компиляций могут делать что-то подобное (учитывая, что они все равно анализируют потоки).

Jit-компиляторы иногда могут даже пойти на шаг дальше и встроить косвенные вызовы, для которых они не могут доказать, что цель статически известна (или там, где ее просто нет). В этом случае они вставляют тест, если целью является ожидаемый результат перед вызовом функции, и используют косвенный вызов, только если это не так (и изменяют в зависимости от того, как часто использовался каждый путь). IIRC .Net Jit делает это, и я предполагаю, что java делает то же самое.

...