LINUX.ORG.RU

LLVM. Зачем он вообще нужен?

 ,


3

6

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

Я не понимаю, почему не использовать просто компиляцию через Си или Си++. Оптимизации сделает компилятор Си. Семантика у LLVM всё равно совпадает с Си, по объёму кода компилятора тоже выигрыша практически нет. Зато если использовать Си, можно использовать любой из компиляторов Си и компилировать для платформ, для которых нет реализации LLVM.

★★★★★
Ответ на: комментарий от Bfgeshka

В смысле https://llvm.org/docs/BitCodeFormat.html ? Это тем более неясно, зачем. Я понимаю, если бы это был JIT байткод как у JVM. Но это просто сжатая запись исходника на LLVM IR, который дальше компилируется в машинный код.

Технически, никто не мешает сделать такой же битовый формат для Си.

monk ★★★★★
() автор топика
Ответ на: комментарий от MOPKOBKA

Можно лучше контролировать процесс оптимизации

Ключиков оптимизации у gcc тоже вагон. И, например, на Эльбрусе у lcc больше настроек оптимизации, чем у llvm.

Так что это только если сравнивать только с clang.

monk ★★★★★
() автор топика

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

anonymous
()

Я не понимаю, почему не использовать просто компиляцию через Си или Си++.

Ты имеешь в виду транспиляцию в Си? Так тоже иногда делают. Например Vala сначала транспилируется в Си, а потом уже сишные исходники компилируются в машинный код. Если надо на коленке набросать прототип самодельного компилируемого ЯП, то тоже проще использовать Си в качестве промежуточного языка.

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

archie
()
Ответ на: комментарий от archie

Быстрее сразу сгенерировать LLVM IR, чем генерировать сишные исходники, а потом тратить время на их токенизацию и парсинг.

Разве? Если сравнить скорость компиляции tcc и clang, то токенизация и парсинг почти мгновенна. LLVM компилирует из IR быстрее, чем tcc из C?

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

LLVM компилирует из IR быстрее, чем tcc из C?

Не имеет смысла сравнивать разные компиляторы. Толку-то от скорости компиляции tcc, если он не может в такие же оптимизации, как шланг. Сравнивать надо в пределах одного и того же компилятора. Например:

  1. Компилируем гипотетический язычок X в LLVM IR, а потом LLVM IR в машинный код.
  2. Транспилируем гипотетический язычок X в код на Си, а потом код на Си компилируем шлангом в машинный код.

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

archie
()
Ответ на: комментарий от anonymous

Poison value можно перехватить, а вот UB в Си нет

Перехват poison value эквивалентен обходу UB.

define i1 @f(i32) {
  %2 = add nsw i32 %0, 1
  %3 = icmp sgt i32 %2, %0
  ret i1 %3
}

Также превращается в ret i1 1, как эквивалентная

int i1(int x)
{
  return x + 1 > 1;
}

превращается в

int i1(int x)
{
  return 1;
}
monk ★★★★★
() автор топика
Ответ на: комментарий от archie

Первый вариант будет быстрее.

На 5%. Ради этого стоило изобретать новый язык? К тому же для LLVM IR надо преобразование SSA делать, оно тоже какое-то время занимает.

monk ★★★★★
() автор топика
Ответ на: комментарий от annulen

Но зачем? Я просто сейчас пытаюсь понять, если писать новый ЯП, зачем выбирать LLVM вместо транспиляции в C++. Транспиляция имеет очевидным достоинством возможность использования библиотек. А в чём достоинство LLVM? Скорость компиляции на 5% выше?

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

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

Это как раз фигня, FFI позволяет использовать сишные либы напрямую из скриптоты.

А в чём достоинство LLVM? Скорость компиляции на 5% выше?

Во-первых, как уже сказали, LLVM — это не только кодогенерация, но и оптимизация. А для компилируемых языков скорость обычно важна (иначе как оправдать затраты времени на компиляцию?).

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

annulen ★★★★★
()
Ответ на: комментарий от annulen

Это как раз фигня, FFI позволяет использовать сишные либы напрямую из скриптоты.

Я про Си++. В том числе заголовочные (header-only).

Во-первых, как уже сказали, LLVM — это не только кодогенерация, но и оптимизация. А для компилируемых языков скорость обычно важна (иначе как оправдать затраты времени на компиляцию?).

Скорость скомпилированного кода для LLVM и clang++ идентична. Для какого-нибудь icc или lcc скорость кода, скомпилированного через C++, будет выше.

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

Э-э-э… А если при компиляции сгенерированного LLVM IR кода, то разве будет проще?

monk ★★★★★
() автор топика

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

Когда компилируется сишный код, то он всё равно переводится в промежуточное представление. И поэтому лишняя стадия трансляции в сишку не нужна. Можно сразу в IR.

ox55ff ★★★★★
()
Ответ на: комментарий от monk

Я про Си++. В том числе заголовочные (header-only).

Не представляю себе, как это может работать. Транспилировать код в C++, чтобы потом в нём юзались шаблонные библиотеки? Да такой код люди с первого раза правильно написать не могут, не то что компиляторы. Твои пользователи будут постоянно видеть простыни шаблонных ошибок.

Скорость скомпилированного кода для LLVM и clang++ идентична

Я не понял, к чему это. Если транспилировать в си и компилировать tcc, то оптимизации не будет.

А если при компиляции сгенерированного LLVM IR кода, то разве будет проще?

Это в принципе не возможно, LLVM не так устроен. Конечно, LLVM может упасть в процессе компиляции, и на экзотических платформах это вполне реально, но тут уже ответственность можно свалить на более крупный проект.

annulen ★★★★★
()
Ответ на: комментарий от ox55ff

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

Можно пример, что в IR можно, а в C нельзя?

Когда компилируется сишный код, то он всё равно переводится в промежуточное представление. И поэтому лишняя стадия трансляции в сишку не нужна. Можно сразу в IR.

Только в clang. Сишных компиляторов много.

monk ★★★★★
() автор топика
Ответ на: комментарий от madcore

Разбор полностью проходит. Занимает 5% от времени компиляции clang. То есть фаза разбора от времени компиляции занимает 5%, остальное оптимизации, которые применяются и к LLVM.

monk ★★★★★
() автор топика
Ответ на: комментарий от dataman

@llvm.expect.*

if (__builtin_expect (x, 0))
  foo ();

@llvm.expect.with.probability.*

https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fexpect_005fwith_005fprobability

monk ★★★★★
() автор топика
Последнее исправление: monk (всего исправлений: 1)