Рубрика «LLVM» - 3

Мы всегда хотим писать код быстро, но за это приходится платить. На обычных высокоуровневых гибких языках можно быстро разрабатывать программы, но после запуска они работают медленно. Например, чудовищно медленно cчитать что-то тяжелое на чистом Python. Си-подобные языки работают гораздо быстрее, но в них легче наделать ошибок, поиск которых сведет весь выигрыш в скорости на нет.

Обычно эта дилемма решается так: сначала пишут прототип на чем-то гибком, например, на Python или R, а потом переписывают на C/C++ или Fortran. Но этот цикл слишком длинный, можно ли обойтись без этого?

А что, если без Python? Julia для машинного обучения и вообще - 1

Возможно, решение есть. Julia — высокоуровневый и гибкий, но при этом быстрый язык программирования. В Julia есть множественная диспетчеризация, встроенный умный компилятор и инструменты метапрограммирования. Подробнее о том, что есть в Julia, расскажет Глеб Ивашкевич (phtRaveller) — основатель datarythmics, которая занимается разработкой систем машинного обучения для промышленности и других отраслей, в прошлом физик.

Глеб объяснит, зачем нужны новые языки и почему иногда Python не хватает. Расскажет, что в Julia интересного, о ее сильных и слабых сторонах, сравнит с другими языками, и покажет, какая у языка перспектива в машинном обучении и вычислениях вообще.

Дисклеймер. Здесь не будет разбора синтаксиса. читатели опытные разработчики, поэтому нет смысла показывать, как написать цикл, например.
Читать полностью »

Оптимизирующий AOT-компилятор обычно структурирован так:

  1. фронтенд, преобразующий исходный код в промежуточное представление
  2. конвейер машинно-независимой оптимизации (IR): последовательность проходов, которые переписывают IR для устранения неэффективных участков и структур, которые не могут быть непосредственно преобразованы в машинный код. Иногда эту часть называют middle-end.
  3. Машинно-зависимый бэкенд для генерации ассемблерного кода или машинного кода.

Как LLVM оптимизирует функцию - 1

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

На данный момент LLVM стала уже очень популярной системой, которую многие активно используют для создания различных компиляторов, анализаторов и т.п. Уже написано большое количество полезных материалов по данной тематике, в том числе и на русском языке, что не может не радовать. Однако в большинстве случаев основной уклон в статьях сделан на frontend и middleend LLVM. Конечно, при описании полной схемы работы LLVM генерация машинного кода не обходится стороной, но в основном данной темы касаются вскользь, особенно в публикациях на русском языке. А при этом у LLVM достаточно гибкий и интересный механизм описания архитектур процессоров. Поэтому данный материал будет посвящен несколько обделенной вниманием утилите TableGen, входящей в состав LLVM.

Причина, по которой компилятору необходимо иметь информацию об архитектуре каждой из целевых платформ вполне очевидна. Естественно, у каждой модели процессора свой набор регистров, свои машинные инструкции и т.д. И компилятору нужно иметь всю необходимую информацию о них, чтобы быть в состоянии генерировать валидный и эффективный машинный код. Компилятор решает различные платформенно-зависимые задачи: производит распределение регистров и т.д. К тому же в бэкендах LLVM также проводятся оптимизации уже на машинном IR, который больше приближен к реальным инструкциям, или же на самих ассемблерных командах. В подобных оптимизациях нужно заменять и преобразовывать инструкции, соответственно вся информация о них должна быть доступна.
Читать полностью »

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

Я расскажу, как сделать это изящно, буквально парой строк в билд-скрипте Gradle-а.
Читать полностью »

Введение

С 2016-го года (с перерывами) я разрабатываю собственный язык программирования. Название данного языка — «Ü». Почему Ü? Потому, что хотелось однобуквенного названия, а все буквы из набора A-Z уже заняты.

Данная статья имеет задачу ознакомить публику с данным языком, дать составить общее представление о нём. Статья не ставит целью описать язык полностью, более полное описание языка, если надо, будет дано в последующих статьях.

Зачем нужен ещё один язык?
Читать полностью »

В этой статье мы рассмотрим, как построить программу на Go, такую, как компилятор или статический анализатор, которая взаимодействует с фреймворком компиляции LLVM, используя язык ассемблера LLVM IR.

TL;DR мы написали библиотеку для взаимодействия с LLVM IR на чистом Go, см. ссылки на код и на пример проекта.

Читать полностью »

В школе, когда мы решали уравнения или считали формулы, мы пытались их сперва сократить несколько раз, к примеру Z = X - (Y + X) сокращается в Z = -Y. В современных компиляторах это подмножество так называемых peephole-оптимизаций, в которых мы по, грубо говоря, набору шаблонов сокращаем выражения, заменяем инструкции на более быстрые для конкретного процессора и т.п. В этой статье я собрал наборчик таких оптимизаций, которые удалось найти в исходниках LLVM, GCC и .NET Core (CoreCLR).

Начнем с простых примеров:

  X * 1        =>  X
-X * -Y        =>  X * Y 
-(X - Y)       =>  Y - X  
X * Z - Y * Z  =>  Z * (X - Y) 

проверим последний пример в С++ и в C#:

int Test(int x, int y, int z) {
    return x * z - y * z;  //  =>  z * (x - y)
}

и посмотрим на ассемблер от Clang (LLVM), GCC, MSVC и .NET Core:
Peephole микрооптимизации в С++ и C# компиляторах - 1

Читать полностью »

Экосистема TensorFlow содержит ряд компиляторов и оптимизаторов, работающих на различных уровнях программного и аппаратного стека. Для тех, кто использует Tensorflow ежедневно, этот многоуровневый стек может порождать трудные для понимания ошибки, как времени компиляции, так и в рантайме, связанные с использованием разного рода железа (GPU, TPU, мобильных платформ и пр.)

Эти компоненты, начиная с графа Tensorflow, могут быть представлены в виде такой диаграммы:

LLVM для Tensorflow, или компилятор эпохи конца закона Мура - 1

На самом деле всё сложнее
Читать полностью »

Компилятор — часть Emscripten. А что, если удалить все свистелки и оставить только его?

Emscripten необходим для компиляции C/C++ в WebAssembly. Но это гораздо больше, чем просто компилятор. Цель Emscripten в том, чтобы полностью заменить ваш компилятор C/C++ и запустить в вебе код, который изначально не предназначен для Сети. Для этого Emscripten эмулирует всю операционную систему POSIX. Если программа использует fopen(), то Emscripten предоставит эмуляцию файловой системы. Если используется OpenGL, то Emscripten предоставит С-совместимый контекст GL, поддерживаемый WebGL. Это немалая работа, и немало кода, который придётся внедрить в итоговый пакет. Но можно ли просто… удалить его?
Читать полностью »

Разработка компилятора — очень тяжёлая задача. Но, к счастью, с развитием проектов наподобие LLVM, решение этой задачи значительно упрощается, что позволяет даже программисту-одиночке создать новый язык, близкий по производительности к C. Работа с LLVM осложняется тем, что эта система представлена огромным объёмом кода, снабжённого небольшой документацией. Для того чтобы попытаться этот недостаток исправить, автор материала, перевод которого мы сегодня публикуем, собирается продемонстрировать примеры кода, написанного на Go, и показать, как они транслируются сначала в Go SSA, а потом — в LLVM IR с использованием компилятора TinyGO. Код Go SSA и LLVM IR был немного отредактирован, из него было удалено то, что не относится к приводимым тут пояснениям, ради того, чтобы эти пояснения оказались бы более понятными.

image

Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js