Tech Talks @NSU: Как приручить дракона: введение в LLVM
-
Upload
tech-talks-nsu -
Category
Education
-
view
153 -
download
1
Transcript of Tech Talks @NSU: Как приручить дракона: введение в LLVM
![Page 1: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/1.jpg)
LLVM: Как приручить дракона?
Дмитрий Каш цын, HDSoftии
![Page 2: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/2.jpg)
Как работает компилятор
1. Прочитать текст программы из файла
2. Записать исполняемый файл
![Page 3: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/3.jpg)
Чуть детальнее
● Разбор лексем и синтаксический анализ
● Построение AST программы
● Преобразования (магия)
● Генерация объектного файла
● Линковка исполняемого файла
![Page 4: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/4.jpg)
4
Но зачем?!*
* http://www.linux.org.ru/gallery/workplaces/10931314
![Page 5: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/5.jpg)
5
Если серьезно
● Развитие computer science не стоит на месте
● Новые идеи — новые языки
● Новые языки — новые компиляторы
● Успех Rust и Go говорит сам за себя
![Page 6: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/6.jpg)
6
Мой уютный компилятор™
● Парсинг исходников
● Представление программы?
● Оптимизация всего и вся
● Целевая архитектура, наборы инструкций
● Аллокация и распределение регистров
● Интероперабельность — системные вызовы, FFI, работа с библиотеками
● Генерация исполняемого файла, линковка
● Отладочная информация
![Page 7: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/7.jpg)
7
Структура команды x86 (OMG)
http://penberg.blogspot.ru/2010/04/short-introduction-to-x86-instruction.html
![Page 8: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/8.jpg)
8
Как угодить всем?
● Языки разные. Очень.
● Разное отношение к данным
● Разные модели памяти
● Разные целевые архитектуры
● Разные наборы инструкций
![Page 9: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/9.jpg)
9
Решение LLVM
● Запись программы в виде, не зависящем от всего вышеперечисленного
● Промежуточное представление — IR код
● Обобщенная система команд
![Page 10: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/10.jpg)
10
Решение LLVM
● Запись программы в виде, не зависящем от всего вышеперечисленного
● Промежуточное представление — IR код
● Обобщенная система команд
Внезапно: LLVM — это не VM o_O
![Page 11: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/11.jpg)
11
Разбор исходного текста
● LLVM считает, что AST уже есть
● Чтобы его получить, нужно провести лексический и синтаксический анализ
● К счастью, это не надо делать вручную
● На помощь придут
– Flex/Bison
– ANTLR
– И другие
![Page 12: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/12.jpg)
12
Так видит программу человек
int gcd(int a, int b) {
while (b != 0) { if (a > b) a = a − b; else b = b − a; }
return a;}
![Page 13: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/13.jpg)
13
Так видит программу компилятор
condition
body
else-bodyif-body
while
variable
name: b
constant
value: 0
compare
op: ≠
branch
compare
op: >assign
bin op
op: −
assign
bin op
op: −
statement
sequence
return
variable
name: a
variable
name: a
variable
name: a
variable
name: a
variable
name: a
variable
name: b
variable
name: b
variable
name: b
variable
name: b
condition
![Page 14: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/14.jpg)
14
Лексический анализ
● Первичный разбор текста программы
● Удаление лишнего шума
● Преобразование потока входных символов в последовательность токенов
![Page 15: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/15.jpg)
15
Лексический анализатор flex
● Позволяет записать правила разбора в текстовом, человеко-читаемом виде
● Регулярные выражения — это сила
● На выходе — токены
![Page 16: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/16.jpg)
16
Входной файл для flex (огрызок)
whitespace [ \r\n\t]*number [0-9]+identifier [a-zA-Z]+
{whitespace} { /* ignore whitespaces */ }
{number} { sscanf(yytext, "%d", &yylval->value); return TOKEN_NUMBER; }
"+" { return PLUS; }"-" { return MINUS; }"(" { return LPAREN; }")" { return RPAREN; }";" { return SEMICOLON; }"," { return COMMA; }"=" { return EQ; }"!=" { return NEQ; }">" { return GTR; }"if" { return IFSYM; }"while" { return WHILESYM; }
![Page 17: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/17.jpg)
17
Синтаксический анализатор bison
● На вход получает поток токенов от лексера и файл описания грамматики
● На основании правил грамматики производит разбор
● На выходе дает древовидное представление программы с которым может работать компилятор
![Page 18: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/18.jpg)
18
Входной файл для bison (огрызок)
input: | input line;
line: '\n' | exp '\n' { complete("result is %g\n", $1); };
exp: TOKEN_NUMBER { $$ = $1; } | exp '+' exp { $$ = $1 + $3; } | exp '-' exp { $$ = $1 - $3; } | exp '/' exp { $$ = $1 / $3; } | exp '*' exp { $$ = $1 * $3; } | '(' exp ')' { $$ = $2; };
Позволяет разбирать арифметические выражения вида (2 + 3 * 4) * 5
![Page 19: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/19.jpg)
19
IR код
● Intermediate Representation
● Запись графа управления в привычном текстовом виде…
![Page 20: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/20.jpg)
20
IR код
● Intermediate Representation
● Запись графа управления в привычном текстовом виде…
но с плюшками:
– Asm-подобный синтаксис, но с параметризованными функциями
– Строгая типизация
– Структуры данных, указатели
– Const, Volatile модификаторы
– Нотация SSA
![Page 21: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/21.jpg)
21
Нотация SSA
● Static Single Assignment
● Переменных — нет о_О
● Все имена встречаются только единожды
● Функциональный стиль описания данных
● Императивный стиль описания операций
![Page 22: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/22.jpg)
22
Что хорошего в SSA?
X ← 1
X ← 2
Y ← X
![Page 23: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/23.jpg)
23
Что хорошего в SSA?
X ← 1
X ← 2
Y ← X
X1←1
X2←2
Y1←X2
![Page 24: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/24.jpg)
24
Что хорошего в SSA?
X ← 1
X ← 2
Y ← X
X1←1 (RIP)
X2←2
Y1←X2
![Page 25: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/25.jpg)
25
Что хорошего в SSA?
X ← 1
X ← 2
Y ← X
X1←1 (RIP)
X2←2 (RIP)
Y1←2
![Page 26: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/26.jpg)
26
Граф потока управления*
● Control flow graph (CFG)
● Узлы — базовые блоки
● Ребра — инструкции переходов
● Базовый блок — линейный участок кода
(a)
(c)
(b)
(d)
* https://en.wikipedia.org/wiki/Control_flow_graph
![Page 27: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/27.jpg)
27
Циклы и ветвления в SSA
![Page 28: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/28.jpg)
28
Циклы и ветвления в SSA
![Page 29: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/29.jpg)
29
Циклы и ветвления в SSA
![Page 30: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/30.jpg)
30
Подсчет суммы массива
int sum_array(int* input, int length) { int sum = 0; for (int i = 0; i < length; ++i) sum += input[i]; return sum;}
![Page 31: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/31.jpg)
31
Листинг IR кода
1 ; Function Attrs: nounwind readonly2 define i32 @sum_array(int*, int)(i32* nocapture readonly %input, i32 %length) #0 {3 %1 = icmp sgt i32 %length, 0 ; а есть вообще что суммировать?4 br i1 %1, label %.lr.ph, label %._crit_edge
5 ._crit_edge: 6 %sum.0.lcssa = phi i32 [ 0, %0 ], [ %4, %.lr.ph ]7 ret i32 %sum.0.lcssa ; возврат результата
8 .lr.ph: 9 %i.02 = phi i32 [ %5, %.lr.ph ], [ 0, %0 ]10 %sum.01 = phi i32 [ %4, %.lr.ph ], [ 0, %0 ] 11 ; вычисление адреса текущего элемента в массиве и его загрузка в регистр12 %2 = getelementptr inbounds i32, i32* %input, i32 %i.02 13 %3 = load i32, i32* %2, align 4 14 ; аккумулирование суммы и инкремент индекса15 %4 = add nsw i32 %3, %sum.01 ; новое значение sum16 %5 = add nuw nsw i32 %i.02, 1 ; новое значение i 17 ; условие выхода18 %exitcond = icmp eq i32 %5, %length 19 ; проверка условия выхода и переход20 br i1 %exitcond, label %._crit_edge, label %.lr.ph21 }
![Page 32: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/32.jpg)
32
Результат clang -O1 -m32
sum_array(int const*, int): mov ecx, dword ptr [esp + 8]xor eax, eaxtest ecx, ecxjle .LBB0_3mov edx, dword ptr [esp + 4]
.LBB0_2: # %.lr.phadd eax, dword ptr [edx]add edx, 4dec ecxjne .LBB0_2
.LBB0_3: # %._crit_edgeret
![Page 33: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/33.jpg)
33
Результат clang -O1 (x64)
sum_array(int const*, int): xor eax, eaxtest esi, esijle .LBB0_2
.LBB0_1: # %.lr.phadd eax, dword ptr [rdi]add rdi, 4dec esijne .LBB0_1
.LBB0_2: # %._crit_edgeret
![Page 34: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/34.jpg)
34
Оптимизации
● Наблюдаемое поведение
● Точки следования
● Эквивалентные преобразования
![Page 35: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/35.jpg)
35
Основные идеи оптимизаций
● Не делать то, что никому не нужно
● Не делать дважды то, что можно сделать один раз (а лучше не делать вообще)
● Если можно получить тот же результат, но меньшими усилиями — это нужно сделать
● Сокращение издержек на всех уровнях
![Page 36: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/36.jpg)
36
Виды оптимизаций
● Peephole оптимизации — буквально «через замочную скважину». Локальные оптимизации в пределах базового блока
● Внутрипроцедурные оптимизации
● Межпроцедурные оптимизации
● Оптимизации во время линковки
![Page 37: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/37.jpg)
37
Loop Invariant Code Motion (LICM)
● Вынос инвариантных значений за пределы цикла
● Перенос значений из тела цикла в базовый блок возврата
int sum_array(int* input, int length) { int sum = 0; for (int i = 0; i < length; ++i) { if (sum > length * 1024 * 1024) printf("note: limit exceeded");
sum += input[i];}
return sum;}
![Page 38: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/38.jpg)
38
Loop Invariant Code Motion (LICM)
● Вынос инвариантных значений за пределы цикла
● Перенос значений из тела цикла в базовый блок возврата
int sum_array(int* input, int length) { int sum = 0; for (int i = 0; i < length; ++i) { if (sum > length * 1024 * 1024) printf("note: limit exceeded");
sum += input[i];}
return sum;}
![Page 39: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/39.jpg)
39
Loop Invariant Code Motion (LICM)
● Вынос инвариантных значений за пределы цикла
● Перенос значений из тела цикла в базовый блок возврата
int sum_array(int* input, int length) { int sum = 0; const int len = length * 1024 * 1024;
for (int i = 0; i < length; ++i) { if (sum > len) printf("note: limit exceeded");
sum += input[i];}
return sum;}
![Page 40: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/40.jpg)
40
Common subexpression elimination (CSE)
● Удаление общих подвыражений
int sum_array(int* input, int length) { int sum = 0; int max = 0; for (int i = 0; i < length; ++i) { max = (input[i] > max) ? input[i] : max; sum += input[i];
}
printf("max was %d\n", max); return sum;}
![Page 41: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/41.jpg)
41
Common subexpression elimination (CSE)
● Удаление общих подвыражений
int sum_array(int* input, int length) { int sum = 0; int max = 0; for (int i = 0; i < length; ++i) { max = (input[i] > max) ? input[i] : max; sum += input[i];
}
printf("max was %d\n", max); return sum;}
![Page 42: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/42.jpg)
42
Common subexpression elimination (CSE)
● Удаление общих подвыражений
int sum_array(int* input, int length) { int sum = 0; int max = 0; for (int i = 0; i < length; ++i) { const int input_i = input[i];
max = (input_i > max) ? input_i : max; sum += input_i;
}
printf("max was %d\n", max); return sum;}
![Page 43: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/43.jpg)
43
Что можно почитать
● blog.llvm.org
● llvm.org/docs
● halt.habrahabr.ru/topics/
● llst.org
![Page 44: Tech Talks @NSU: Как приручить дракона: введение в LLVM](https://reader034.fdocuments.net/reader034/viewer/2022052216/5880003c1a28ab3a1e8b74c1/html5/thumbnails/44.jpg)
Спасибо за внимание!