LINUX.ORG.RU

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

 ,


3

6

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

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

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

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

А если уж браться за C++, то нужно иметь в виду, что для него нет супербыстрых компиляторов, не строящих SSA. Парсинг C++ вообще очень долгое и мучительное занятие, которое могут позволить себе только «большие» компиляторы.

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

Стильно, модно, молодёжно.

Согласен. Поэтому и появился вопрос в теме.

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

Вот теперь пытаюсь понять, а технические достоинства у этого выбора есть или только психологические.

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

На 5%. Ради этого стоило изобретать новый язык?

Да, для C/C++ байтодрочеров, помешанных на производительности, даже 5% ускорение - это уже железный аргумент за LLVM. Бинарное промежуточное представление кода считается каноном, в отличие от текстового представления на Си. Ну и да, как правильно отметили выше, при компиляции промежуточного сишного выхлопа могут вылезти ошибки компиляции, которые для пользователя будут полностью нечитабельны.

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

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

Да, для C/C++ байтодрочеров, помешанных на производительности, даже 5% ускорение - это уже железный аргумент за LLVM.

Скорость компиляции, а не скорость скомпилированного кода. Если бы C/C++ байтодрочерам была важна скорость компиляции, давно перешли бы на что-то паскалеподобное.

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

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

Я тут играюсь с mlton, запуская всякие бенчмарки.

MLton - это оптимизирующий компилятор Standard ML.

У него есть разные кодогенраторы -codegen {native,c,llvm}. Самый быстрый код получается с «native», «c» и «llvm» чуть медленнее - 1-2%.

Самое интересное, код на Си mlton собирает с «-O1». Я решил собрать с «-O3» (без разницы clang или gcc) - скорость ниже на 25-30%.

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

А LLVM так как «не язык», убрал этот психологический барьер.

LLVM дал набор библиотек, позволяющих без проблем встроить в свой компилятор готовую связку «оптимизатор-кодогенератор-ассемблер». Никто файлы с биткодом не генерирует.

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

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

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

Давай для определённости сравнивать LLVM и GCC.

Так у GCC то же самое: семейство компиляторов с большой общей частью.
Тогда зачем они нужны, если есть LLVM с лицензией Apache?

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

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

Скорость компиляции будет на условные 5% выше по сравнению с Си. По сравнению с C++ выигрыш может быть значительно выше. И не только в скорости компиляции будет выигрыш. Но это в теории. Если подходить серьёзно, то надо замеры проводить на практике.

В любом случае, новый язык надо вначале транслировать в C++. Затем уже можно переводить на LLVM или на Си, если практика покажет, что без этого никак.

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

Тогда зачем они нужны, если есть LLVM с лицензией Apache?

Чтобы компилировать через код Си и иметь хорошую скорость на всех платформах, где есть Си, а не только на тех, где есть LLVM.

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

Если уточнение «в любом современном оптимизирующем компиляторе», тогда соглашусь. Скоро будет один браузер и один компилятор. А все остальные к перечисленным только интерфейсы прикручивать.

А если Микрософт перейдёт на ядро Линукса, то и одна ОС…

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

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

Возьмём то, что нагенерировал V: https://github.com/vlang/vc (~6.4M).

$ time tcc v.c

real    0m0.253s
user    0m0.217s
sys     0m0.036s

$ time gcc-14 v.c

real    0m12.241s
user    0m10.059s
sys     0m0.235s

$ time clang-20 v.c

real    0m5.018s
user    0m4.806s
sys     0m0.154s
dataman ★★★★★
()
Ответ на: комментарий от monk

Скоро будет один браузер и один компилятор.

GCC намного лучше чем Clang и в его развитии заинтересован Intel, RH, так что сомнительно.

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

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

Только в clang.

Вот https://github.com/libfirm/cparser, например:

cparser is a recursive descent C99 parser written in C99. It contains a preprocessor, lexer, parser, constructs an AST and does semantic analysis. It acts as a frontend to the libFirm intermediate representation library. This way optimization and code generation is performed.

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

Вот, если бы gcc умел компилировать gimple или в какой-нибудь из множества промежуточных представлений, то можно было бы генерировать сразу это промежуточное представление…

Хотя эти промежуточные представления врядли совместимы между версиями и целевыми платформами (target).

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

А теперь с оптимизацией.

$ time clang-16 -O3 -Wno-everything v.c

real    2m29,479s
user    2m28,609s
sys     0m0,663s

$ time clang-16 -O3 -Wno-everything v.ll

real    1m59,729s
user    1m59,176s
sys     0m0,454s

Не сильно отличается. Хотя и не 5%.

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

Не сильно отличается. Хотя и не 5%.

clang что-то ещё до llvm оптимизирует. emit-llvm с -O3 и без на почти те полминуты отличается.

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

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

А как по-твоему, делает оптимизации компилятор C? Низкоуровневые оптимизации типа распределения регистров делаются на низкоуровневом представлении кода, если это не IR то что-то приближенное к машкоду целевой платформы, никакого C там уже близко нет. Ровно в это место и приходит LLVM, потому что умеет этим с представлением управляться независимо и от языка и от платформы.

Семантика у LLVM всё равно совпадает с Си

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

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

Так-то еще есть оптимизации на уровне языка программирования.

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

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

Чтобы компилировать через код Си и иметь хорошую скорость на всех платформах, где есть Си, а не только на тех, где есть LLVM.

Там где нет LLVM, у C не может быть хорошей скорости)))

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

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

Так все UB из C реализованы в LLVM. И из-за этого периодически просачиваются в unsafe Rust, например.

Просто семантика языков бывает разная. Например, у ассемблера семантика не совпадает с Си: на нём доступ за пределы массива не UB, а либо возврат какого-то значения, либо прерывание ОС. И вообще понятия UB в ассемблере нет. Любая операция для любых аргументов может делать только очень ограниченный набор действий.

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

Там где нет LLVM, у C не может быть хорошей скорости)))

На Эльбрусе у Си очень хорошая скорость, а LLVM там появился очень недавно.

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

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

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

Так как это относится к IR vs C?

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

llvm - это только компилятор под архитектуру. А на деле нужен тулчейн, и с этим у gcc и мимикрирующих под gcc деля обстоят намного лучше.

Это лютый бред, конечно же. Это gcc - только компилятор бесполезный как минимум без линкера и binutils.

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

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

llvм же содержит сразу весь комплект

Как «комплект», он даже более ограничен, чем просто компилятор под архитектуру.

Тем временем, тулчейны, содержащие gcc, поддерживают намного больше платформ.

Это лютый бред

Учись читать, а не выдирать ключевые слова

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

Как «комплект», он даже более ограничен, чем просто компилятор под архитектуру.

Заканчивай позориться. То что этот комплект самодостаточен показывает хотя бы то что он полностью заменил gcc, гнутый ld, binutils и gcc на тех системах которые на него перешли, например freebsd.

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

полностью заменил gcc, гнутый ld, binutils и gcc на тех системах которые на него перешли, например freebsd.

Живи на freebsd, там все хорошо. И позорится не надо.

anonymous
()

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

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

Термин UB применим только к оптимизациям и не существует в отрыве от них.

Нет. UB — это произвольное поведение при встрече соответствующего примера в коде. Безотносительно оптимизаций. Для процессора UB — это, например, превышение рабочей температуры или облучение высокоэнергетическими частицами.

но если ты вдруг решишь делать преобразования машинного кода, то некоторые из них возможны только при определённых допущениях об обрабатываемых данных

Верно. Но если для Си есть код, для которого утверждается, что он может делать что угодно, то для ассемблера такого кода не существует.

оптимизация руководствуется таким допущением, а оно нарушается

Может руководствоваться только если есть «невозможный код». Если любой операнд с любыми параметрами допустим, то UB не может быть допущением.

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

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

Не хотят зависеть от gcc, хотят по максимуму всё своё иметь.

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

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

Формулировка предполагает, что LLVM это что-то, без чего нельзя обойтись, и вопрошающий хочет узнать конкретные аспекты этой надобности. Но ведь абсолютной надобности в нём нет. Его используют просто потому что так получилось.

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

В MJIT для Ruby так и сделали: он писал на диск сгенерированый Си-код, который компилировался вызовом внешнего компилятора. Вполне себе подход. Правда, вызовы внешних программ могут занять довольно много времени.

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

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

[user]monk[/user], как ты забыл про TCO? Мы ж тут недавно мусолили эту тему

anonymous
()

если использовать Си, можно использовать любой из компиляторов Си и компилировать для платформ, для которых нет реализации LLVM.

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

olelookoe ★★★
()

Вопрос вообще некорректно поставлен. LLVM это уже и есть бэкенд компилятора сишечки и крестов, т.е. это кишки Clang, по сути.

И LLVM не подходит ни для хера, кроме C, C++ и семантически идентичных языков.

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

lovesan ★★★
()