LLVM и будущее оптимизации

Я понимаю, что LLVM имеет долгий путь, но теоретически, могут оптимизации, которые находятся в GCC/ICC/etc. для отдельных языков применяется байтовый код LLVM? Если да, означает ли это, что любой язык, который компилируется в байтовый код LLVM, может быть одинаково быстрым? Или языковые оптимизации (до этапа байт-кода LLVM) всегда будут играть большую роль в оптимизации любой конкретной программы.

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

7 ответов


В общем, нет.

например, в Haskell общей оптимизацией является анализ строгости, который позволяет компилятору определить, какие переменные всегда находятся в нормальном виде и поэтому могут быть принудительно + встроены без изменения семантики программы. Это невозможно с LLVM.

объяснение: в Haskell, функция (Int, Int) -> Int более или менее эквивалентно типу В C:

typedef int (*returns_int)();
struct pair { returns_int first, second};
typedef struct pair *(*returns_pair)();

int function(returns_pair arg);

компилятор может проанализировать function и определите, что он всегда оценивает свой аргумент и всегда извлекает содержимое, Преобразуя функцию в это:

int function(int x, int y); // note that it takes *two* arguments now

это далеко за пределами возможностей LLVM. Может быть, в будущем, с какой-то действительно тяжелой межпроцедурной оптимизацией... но, говоря реалистично, этого не произойдет в обозримом будущем.

Пример 2: есть Java VMs, которые могут преобразовывать виртуальные вызовы функций в прямые вызовы функций. Однако, это не что - то, что LLVM может сделать-потому что это преобразование должно быть отменено динамически, если загружен другой класс, который реализует тот же интерфейс.

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


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

например, относительно легко оптимизировать код C для максимизации эффективность кэша (снижение медленного чтения из памяти), в то время как в Haskell это намного сложнее. Хаки указателей невозможны в Java. Как и стратегия выделения огромного куска памяти и его разбиения вручную.

таким образом, некоторые языки всегда будут медленнее просто потому, что они не допускают одинакового уровня оптимизации. Обратите внимание, что я не обязательно говорю, что это плохо, потому что с этой медлительностью приходят чрезвычайно мощные конструкции.

Я думаю, что лучший способ взглянуть на это заключается в том, что LLVM позволит применять определенный набор оптимизаций ко всем языкам, которые компилируются до него. Таким образом, пока это будет сделайте такие языки быстрее, это не сделает их одинаково быстро.

Edit: указатель хаки в Haskell. Так много возможностей ...


Это интересный вопрос, но я боюсь, что вам не хватает некоторых представлений о том, что делают компиляторы.

в компиляторе всегда будет несколько этапов оптимизации.

  • некоторые оптимизации зависят от правил языков, например, в C++ вы можете оптимизировать некоторые вызовы конструкторов копирования/перемещения.
  • некоторые оптимизации широко доступны (преобразования цикла, хвостовые вызовы)
  • некоторые оптимизации зависят от оборудования (ССЭ ММХ)

компилятор LLVM применяет все 3... но начиная с LLVM IR, а не с C или Java или что-то еще.

Это работа переднего плана, чтобы обеспечить подходящий LLVM ИК.

например, как отметил @Dietrich Epp, ИК не очень подходит для функциональных языков. Поэтому необходимо выполнить множество оптимизаций Haskell до представление понижено к ИК.

другой источник не-оптимизация заключается в том, что конкретная среда выполнения может поставляться с языками. Haskell имеет сложную среду выполнения с пулом искр, легкими потоками, упреждением перед системными вызовами,кражей работы и т. д... ИК не подходит для представления этой богатой среды, и никакая оптимизация не производится в этой организации.


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

но для обширной оптимизации также важен интерфейс, так как он знает гораздо больше деталей о компилируемой программе. Вещи стека LLVM это нелегко выяснить. Поэтому для генерации эффективных программ также интерфейс должен оптимизировать код.


возвращаясь к вашему вопросу


Я не знаю никаких подробностей о формате байт-кода используемого кода LLVM, но я думаю, что ответ на ваш вопрос нет.

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

также могут быть некоторые другие различия между языками программирования, которые могут повлиять на производительность.


здесь я нашел отчет, с легким для начинающих обзор ЦУС против отличия LLVM с : в Clang/LLVM с зрелости оценка доклада Доминик Fandrey