- PVSM.RU - https://www.pvsm.ru -
Месяц назад я попытался сосчитать [1], сколько разных инструкций поддерживается современными процессорами, и насчитал 945 в Ice Lake. Комментаторы затронули интересный вопрос [2]: какая часть всего этого разнообразия реально используется компиляторами? Например, некто Pepijn de Vos в 2016 подсчитал [3], сколько разных инструкций задействовано в бинарниках у него в /usr/bin, и насчитал 411 — т.е. примерно треть всех инструкций x86_64, существовавших на тот момент, не использовались ни в одной из стандартных программ в его ОС. Другая любопытная его находка — что код для x86_64 на треть состоит из инструкций mov
. (В общем-то известно [4], что одних инструкций mov
достаточно, чтобы написать любую программу.)
Я решил развить исследование de Vos, взяв в качестве «эталонного кода» компилятор LLVM/Clang. У него сразу несколько преимуществ перед содержимым /usr/bin неназванной версии неназванной ОС:
Начну со статистики по мартовскому релизу LLVM 10.0:
ISA | Размер бинарника | Размер секции .text | Общее число инструкций | Число разных инструкций |
---|---|---|---|---|
AArch64 | 97 МБ | 74 МБ | 13,814,975 | 195 |
ARMv7A | 101 МБ | 80 МБ | 15,621,010 | 308 |
i386 | 106 МБ | 88 МБ | 20,138,657 | 122 |
PowerPC64LE | 108 МБ | 89 МБ | 17,208,502 | 288 |
SPARCv9 | 129 МБ | 105 МБ | 19,993,362 | 122 |
x86_64 | 107 МБ | 87 МБ | 15,281,299 | 203 |
В прошлом топике комментаторы упомянули [6], что самый компактный код у них получается для SPARC. Здесь же видим, что бинарник для AArch64 оказывается на треть меньше что по размеру, что по общему числу инструкций.
А вот распределение по числу инструкций:
Неожиданно, что код для SPARC на 11% состоит из nop
-ов, заполняющих branch delay slots [7]. Для i386 среди самых частых инструкций видим и int3
, заполняющую промежутки между функциями, и nop
, используемую для выравнивания циклов на строки кэша. Наблюдение de Vos о том, что код на треть состоит из mov
, подтверждается на обоих вариантах x86; но даже и на load-store-архитектурах mov
оказывается если не самой частой инструкцией, то второй после load.
А как набор используемых инструкций менялся со временем?
Единственная ISA, для которой в каждом релизе есть официальный бинарник — это i386:
Серая линия, отложенная на правой оси — это число разных инструкций, использованных в компиляторе. Как мы видим, некоторое время назад компилятор компилировался гораздо разнообразнее. int3
стала использоваться для заполнения промежутков только с 2018; до этого использовались такие же nop
, как и для выравнивания внутри функций. Здесь же видно, что выравнивание внутри функций стало использоваться с 2013; до этого nop
-ов было гораздо меньше. Ещё интересно, что до 2016 mov
-ы составляли почти половину компилятора.
Самые первые версии LLVM, до появления clang, выпускались ещё и с бинарниками для SPARC. Потом поддержка SPARC утратила актуальность, и вновь она появилась лишь через 14 лет — с на порядок увеличившимся числом nop
-ов:
Исторически следующая ISA, для которой выпускались бинарники LLVM — это PowerPC: сначала для Mac OS X и затем, после десятилетнего перерыва, для RHEL. Как видно из графика, переход после этого перерыва к 64-битному варианту ISA сопровождался заменой большинства lwz
на ld
, и вдобавок удвоением разнообразия инструкций:
В бинарниках для x86_64 и ARM частота использования разных инструкций почти не изменялась:
При подсчёте инструкций ARM я отсекал суффиксы условий [8] — вместе с ними получалось около тысячи разных инструкций, но даже и без них ARM сильно опережает другие ISA по разнообразию генерируемых инструкций. Таким образом, слой b
на этом графике включает и все условные переходы тоже. Для остальных ISA, где условными могут быть только переходы и немногие другие инструкции, суффиксы условий при подсчёте не отсекались.
Наконец, самая недавняя ISA, для которой публикуются официальные бинарники — это AArch64. Здесь интересно то, что orr
с прошлого года почти перестала использоваться:
PowerPC и AArch64 оказались единственными ISA, для которых число разных используемых инструкций всё растёт и растёт.
Автор: tyomitch
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/vizualizatsiya-danny-h/354101
Ссылки в тексте:
[1] попытался сосчитать: https://habr.com/ru/post/503486/
[2] затронули интересный вопрос: https://habr.com/ru/company/huawei/blog/503194/#comment_21644072
[3] подсчитал: http://pepijndevos.nl/2016/08/24/x86-instruction-distribution.html
[4] известно: https://www.pvsm.ruhttp://web.archive.org/web/20190331191157/https://www.cl.cam.ac.uk/~sd601/papers/mov.pdf
[5] releases.llvm.org/download.html: https://releases.llvm.org/download.html
[6] упомянули: https://habr.com/ru/company/huawei/blog/503194/#comment_21652280
[7] branch delay slots: https://en.wikipedia.org/wiki/Delay_slot
[8] суффиксы условий: http://www.keil.com/support/man/docs/armasm/armasm_dom1359731161338.htm
[9] Источник: https://habr.com/ru/post/506832/?utm_source=habrahabr&utm_medium=rss&utm_campaign=506832
Нажмите здесь для печати.