- PVSM.RU - https://www.pvsm.ru -
CE — потрясающий инструмент. Если вы с ним не знакомы, то прервите чтение и перейдите на веб-сайт [1] CE, где вы увидите примерно такой экран:
Предупреждение: вы забираетесь в «кроличью нору», на которую можете потратить несколько часов своего времени.

В основе CE лежит очень простая идея. Достаточно ввести исходный код в левую панель, и сайт мгновенно покажет вам на правой панели скомпилированный результат (обычно на языке ассемблера).
CE поддерживает 69 языков, более двух тысяч компиляторов и широкий спектр архитектур, включая x86, arm, risc-v, avr, mips, vax, tensa, 68k, PowerPC, SPARC и даже древний 6502.
То есть теперь для просмотра результата работы компилятора достаточно открыть godbolt.org [1] и скопировать туда блок кода.
Это само по себе удивительно, но у CE есть гораздо больше возможностей. Это инструмент, который должны знать все интересующиеся компиляторами и архитектурами компьютеров. В статье мы сможем лишь поверхностно рассмотреть функции CE. Вам стоит самим перейти на сайт CE и попробовать всё самостоятельно.
Однако нам стоит начать с предыстории CE.
CE на сайте godbolt.org [1], потому что его первым автором был Мэтт Годболт, начавший этот проект в 2012 году. Цитата из поста [3] Мэтта, посвящённого десятой годовщине CE:
Десять лет назад я получил разрешение на перевод в open source небольшого инструмента под названием GCC Explorer [4]. Я разработал его примерно за неделю своего свободного времени на node.js у своего работодателя DRW [5]. Всё остальное, как говорится, стало достоянием истории.
Спустя несколько лет стало очевидно, что GCC Explorer — это уже нечто большее, чем просто GCC, и 30 апреля 2014 года он стал называться «Compiler Explorer».
Недавно Мэтт поделился историей CE в замечательном подкасте Microarch [6] Дэна Магнума.
Стоит послушать интервью Мэтта целиком (ссылки на Spotify [7], YouTube [8] и Apple Podcasts [9]), так как в нём есть много интересных рассуждений об архитектуре, истории компьютеров и CE.
Мэтт Годболт присоединился к обсуждению первых микропроцессоров, работы в игровой отрасли, оптимизации производительности на современных CPU x86 и вычислительной инфраструктуры отрасли финансового трейдинга. Также мы обсудили работу Мэтта по переносу YouTube на первые мобильные телефоны и историю Compiler Explorer
Сам Мэтт также провёл подкаст с Беном Рэди Two’s Complement [10], в том числе эпизод о будущем CE (ссылки на Spotify [11], YouTube [12] и Apple Podcasts [13]), в котором гораздо подробнее рассказывается о текущем статусе проекта.
CE — это опенсорсный проект, исходники которого выложены на GitHub [14], то есть при наличии времени и опыта вы можете хостить CE самостоятельно.
Большинство людей пользуется онлайн-версией CE, которая бесплатна и поддерживается благодаря пожертвованиям и спонсорам.
Для чего можно использовать CE? В этом году Мэтт Годболт выступил с докладом, описывающим различные способы применения CE и его новых функций
Давайте вкратце рассмотрим самые простые способы использования CE.
Мы можем сравнивать ассемблерный код для различных архитектур. В чём отличие кода для x86-64 от кода для ARM64 и RISC-V? Ответ можно узнать всего за несколько секунд. Вот x86-64 [15] (все примеры созданы с помощью GCC 14.1):
square(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
imul eax, eax
pop rbp
ret
А вот ARM64 [16]:
square(int):
sub sp, sp, #16
str w0, [sp, 12]
ldr w0, [sp, 12]
mul w0, w0, w0
add sp, sp, 16
ret
RISC-V [17] (64-битный):
square(int):
addi sp,sp,-32
sd ra,24(sp)
sd s0,16(sp)
addi s0,sp,32
mv a5,a0
sw a5,-20(s0)
lw a5,-20(s0)
mulw a5,a5,a5
sext.w a5,a5
mv a0,a5
ld ra,24(sp)
ld s0,16(sp)
addi sp,sp,32
jr ra
Код вполне в духе RISC. А как насчёт чего-то более CISC наподобие VAX [18]?
square(int):
.word 0
subl2 $4,%sp
mull3 4(%ap),4(%ap),%r0
ret
Или простого 8-битного CPU наподобие 6502 [19]:
square(int): ; @square(int)
pha
clc
lda __rc0
adc #254
sta __rc0
lda __rc1
adc #255
sta __rc1
pla
clc
ldy __rc0
sty __rc6
ldy __rc1
sty __rc7
sta (__rc6)
ldy #1
txa
sta (__rc6),y
lda (__rc6)
sta __rc4
lda (__rc6),y
tax
lda (__rc6)
sta __rc2
lda (__rc6),y
sta __rc3
lda __rc4
jsr __mulhi3
pha
clc
lda __rc0
adc #2
sta __rc0
lda __rc1
adc #0
sta __rc1
pla
rts
А если вас интересует Nvidia CUDA, то CE может показать вам код ptx [20].

CE — отличный инструмент для изучения языка ассемблера. Достаточно навести курсор на команду, после чего откроется всплывающее окно с описанием команды.

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

Там, в свою очередь, можно найти ссылки на веб-сайт документации по набору команд x86 [21] Феликса Клотье.
Код на Arm ведёт к документации для Arm. Однако меня немного расстроило отсутствие документации для языка ассемблера Vax!
Затем мы можем сравнить результат работы разных компиляторов. Вот сравнение gcc и clang [22]. Логично, что код, сгенерированный для такой простой функции, почти одинаков.

Для компиляторов на основе LLVM [23] CE может показывать [24] LLVM Intermediate Representation (LLVM IR). Подробнее LLVM IR объясняется здесь [25]:
Его флагманский продукт — это Clang, высококлассный компилятор C/C++/Objective-C. Clang реализует традиционную архитектуру компилятора: фронтенд, который парсит исходный код в AST и понижает его до промежуточного представления (IR), оптимизатор («мидл-енд»), преобразующий IR в более качественное IR, и бэкенд, преобразующий, IR в машинный код для конкретной платформы.
То есть LLVM — это промежуточный этап перед генерацией ассемблера компилятором. LLVM IR показано справа внизу:

Также CE предоставляет доступ ко множеству инструментов, позволяющих лучше понять наш код и способ его исполнения. Например, мы можем добавить вывод [26] анализатора машинного кода LLVM [27] (llvm-mca), который позволяет нам подробнее изучить то, как машинный код работает на реальном CPU.
Окно llvm-mca показано слева внизу.

llvm-mca симулирует исполнение кода на реальной машине и предоставляет информацию об ожидаемой производительности.
В нашем простом примере llvm-mca сообщает нам, что можно ожидать выполнения 100 итераций за 105 тактов симулируемой машины.
Iterations: 100
Instructions: 300
Total Cycles: 105
Total uOps: 300
Dispatch Width: 6
uOps Per Cycle: 2.86
IPC: 2.86
Block RThroughput: 1.0
Если добавить опцию -timeline , то мы получим диаграмму со временем исполнения команд при движении через CPU.
Цитата из документации llvm-mca:
Режим timeline позволяет просмотреть подробный отчёт о переходах состояний каждой команды по конвейеру команд. Этот режим включается опцией командной строки
-timeline. В процессе переходов команд по различным этапам конвейера их состояния отображаются в отчёте. Состояния представлены следующими символами:
- D: команда отправлена
- e: исполнение команды
- E: команда исполнена
- R: команда удалена
- =: команда уже отправлена, ожидает исполнения
- — : команда исполнена, ожидает удаления
Вот timeline нашего простого примера:
Timeline view:
01234
Index 0123456789
[0,0] DR . . . mov eax, edi
[0,1] DeeeER . . imul eax, edi
[0,2] DeeeeeER . . ret
[1,0] D------R . . mov eax, edi
[1,1] D=eeeE-R . . imul eax, edi
[1,2] DeeeeeER . . ret
[2,0] .D-----R . . mov eax, edi
[2,1] .D=eeeER . . imul eax, edi
[2,2] .DeeeeeER . . ret
[3,0] .D------R . . mov eax, edi
[3,1] .D==eeeER . . imul eax, edi
[3,2] .DeeeeeER . . ret
[4,0] . D-----R . . mov eax, edi
[4,1] . D==eeeER. . imul eax, edi
[4,2] . DeeeeeER. . ret
[5,0] . D------R. . mov eax, edi
[5,1] . D===eeeER . imul eax, edi
[5,2] . DeeeeeE-R . ret
[6,0] . D------R . mov eax, edi
[6,1] . D===eeeER . imul eax, edi
[6,2] . DeeeeeE-R . ret
[7,0] . D-------R . mov eax, edi
[7,1] . D====eeeER . imul eax, edi
[7,2] . DeeeeeE--R . ret
[8,0] . D-------R . mov eax, edi
[8,1] . D====eeeER. imul eax, edi
[8,2] . DeeeeeE--R. ret
[9,0] . D--------R. mov eax, edi
[9,1] . D=====eeeER imul eax, edi
[9,2] . DeeeeeE---R ret
Если вас интересуют интерпретируемые языки, например, Python, то CE может отображать байт-код [28], сгенерированный интерпретатором Python или Ruby. Вот пример с Python.

Теперь CE даже предоставляет простую, но завершённую IDE [29], в том числе функциональность CMake [30] и возможность запуска программ и просмотра результатов.

Ещё одна функция CE заключается в возможности увидеть, насколько умны современные компиляторы. Мэтт Годболт даже выступил со множеством докладов по этой теме. Вот доклад за 2017 год:
А вот более свежий:
А вот статья на ACM: Optimizations in C++ Compilers [31]. Цитата из введения:
В этой статье рассказывается о некоторых концепциях компиляторов и генерации кода, а затем проливается свет на крайне впечатляющие преобразования, которые выполняют компиляторы, с практическими демонстрациями моих любимых оптимизаций. Надеюсь, вы оцените важность подобных оптимизаций, которых можно ждать от компилятора, и захотите глубже исследовать эту тему. Важнее всего, чтобы вы научились любить исследование ассемблерного вывода и уважать высокое качество проектирования компиляторов.
CE даже можно использовать как интересный ресурс, чтобы понять, с какими языками работают пользователи. Это можно сделать при помощи Grafana CE Dashboard [32].

C++ — это язык по умолчанию, так что, возможно, на него не стоит обращать внимание, а вот то, что Rust в четыре раза менее популярен, чем C, — это любопытно.
Есть также страница [33] StatHat, на которой отображается рост использования CE на протяжении нескольких лет.

Сейчас пользователи выполняют примерно 18 миллионов компиляций в год.
Это приблизительно 1,5 миллиона в месяц, 50 тысяч в день, 2 тысяч в час, 30 в минуту или по одной каждые две секунды. Всё это работает на Amazon Web Services и стоит примерно $2500 ежемесячных затрат на
Если вам всего этого недостаточно, то скажу, что сейчас Мэтт снимает потрясающую серию видео с YouTube-каналом Computerphile, в которой объясняет основы работы микропроцессоров. Первым в серии идёт видео «Что такое машинный код» [35]:
Список остальных серий:
Надеюсь, это ещё не всё!

В архитектуре x86 команда MOV Тьюринг-полная [39]. В качестве последнего примера приведу наш простой код, скомпилированный при помощи movfuscator [40], использующего только команды MOV.
Автор: ru_vds
Источник [41]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/391532
Ссылки в тексте:
[1] веб-сайт: https://godbolt.org
[2] хостится: https://www.reg.ru/?rlink=reflink-717
[3] поста: https://xania.org/202206/happy-birthday-ce
[4] GCC Explorer: https://web.archive.org/web/20120525042912/https://gcc.godbolt.org/
[5] DRW: https://www.drw.com/
[6] Microarch: https://microarch.club
[7] Spotify: https://open.spotify.com/episode/2FxzRheJfpDlYO9CY4gaKY?si=IDPYWYNhRbuWzh0_o2Lbiw
[8] YouTube: https://www.youtube.com/watch?v=rd8pGMIYU2Q
[9] Apple Podcasts: https://podcasts.apple.com/gb/podcast/101-matt-godbolt/id1730476827?i=1000652012264
[10] Two’s Complement: https://www.twoscomplement.org
[11] Spotify: https://open.spotify.com/show/52irDllU36Y3mOBbBIxyNd?si=4f2494b30202409f
[12] YouTube: https://youtube.com/playlist?list=PL2HVqYf7If8fd0OpSIKhFdIPjgZcV7aT2&feature=shared
[13] Apple Podcasts: https://podcasts.apple.com/gb/podcast/twos-complement/id1546393988
[14] GitHub: https://github.com/compiler-explorer/compiler-explorer
[15] x86-64: https://godbolt.org/z/37K3G5czq
[16] ARM64: https://godbolt.org/z/4bo5c3zE3
[17] RISC-V: https://godbolt.org/z/vTMPq1hTa
[18] VAX: https://godbolt.org/z/v1v7vcTWK
[19] 6502: https://godbolt.org/z/3esaYzYss
[20] ptx: https://godbolt.org/z/8eq9bd7YG
[21] веб-сайт документации по набору команд x86: https://www.felixcloutier.com/x86/
[22] gcc и clang: https://godbolt.org/z/WYec43jor
[23] LLVM: https://llvm.org
[24] показывать: https://godbolt.org/z/snbT181fG
[25] здесь: https://mcyoung.xyz/2023/08/01/llvm-ir/
[26] добавить вывод: https://godbolt.org/z/6VpQxD
[27] анализатора машинного кода LLVM: https://llvm.org/docs/CommandGuide/llvm-mca.html
[28] байт-код: https://opensource.com/article/18/4/introduction-python-bytecode
[29] завершённую IDE: https://godbolt.org/z/WE9T6K17W
[30] CMake: https://cmake.org
[31] Optimizations in C++ Compilers: https://dl.acm.org/doi/pdf/10.1145/3371595.3372264
[32] Grafana CE Dashboard: https://ce.grafana.net/public-dashboards/326d9aa2606b4efea25f4458a4c3f065?orgId=0&refresh=1m
[33] страница: https://www.stathat.com/s/SO1rSvjtT07k
[34] Patreon CE: https://www.patreon.com/mattgodbolt/about
[35] «Что такое машинный код»: https://www.youtube.com/watch?v=8VsiYWW9r48
[36] Как CPU выполняют математические вычисления: https://www.youtube.com/watch?v=nhXevKMm3JI
[37] Конвейеры CPU: https://www.youtube.com/watch?v=BVNx3wtJ9vs
[38] Как в CPU работает прогнозирование ветвления: https://www.youtube.com/watch?v=nczJ58WvtYo
[39] команда MOV Тьюринг-полная: https://stackoverflow.com/questions/61048788/why-is-mov-turing-complete
[40] movfuscator: https://github.com/xoreaxeaxeax/movfuscator
[41] Источник: https://habr.com/ru/companies/ruvds/articles/815675/?utm_source=habrahabr&utm_medium=rss&utm_campaign=815675
Нажмите здесь для печати.