- 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 неназванной версии неназванной ОС:

  1. С ним удобно работать: это один огромный бинарник, по размеру сопоставимый со всем содержимым /usr/bin среднестатистического линукса;
  2. Он позволяет сравнить разные ISA: на releases.llvm.org/download.html [5] доступны официальные бинарники для x86, ARM, SPARC, MIPS и PowerPC;
  3. Он позволяет отследить исторические тренды: официальные бинарники доступны для всех релизов начиная с 2003;
  4. Наконец, в исследовании компиляторов логично использовать компилятор и в качестве подопытного объекта :-)

Начну со статистики по мартовскому релизу 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 оказывается на треть меньше что по размеру, что по общему числу инструкций.

А вот распределение по числу инструкций:
Сколько инструкций процессора использует компилятор? - 1 Сколько инструкций процессора использует компилятор? - 2 Сколько инструкций процессора использует компилятор? - 3 Сколько инструкций процессора использует компилятор? - 4 Сколько инструкций процессора использует компилятор? - 5 Сколько инструкций процессора использует компилятор? - 6

Неожиданно, что код для SPARC на 11% состоит из nop-ов, заполняющих branch delay slots [7]. Для i386 среди самых частых инструкций видим и int3, заполняющую промежутки между функциями, и nop, используемую для выравнивания циклов на строки кэша. Наблюдение de Vos о том, что код на треть состоит из mov, подтверждается на обоих вариантах x86; но даже и на load-store-архитектурах mov оказывается если не самой частой инструкцией, то второй после load.

А как набор используемых инструкций менялся со временем?

Единственная ISA, для которой в каждом релизе есть официальный бинарник — это i386:
Сколько инструкций процессора использует компилятор? - 7

Серая линия, отложенная на правой оси — это число разных инструкций, использованных в компиляторе. Как мы видим, некоторое время назад компилятор компилировался гораздо разнообразнее. int3 стала использоваться для заполнения промежутков только с 2018; до этого использовались такие же nop, как и для выравнивания внутри функций. Здесь же видно, что выравнивание внутри функций стало использоваться с 2013; до этого nop-ов было гораздо меньше. Ещё интересно, что до 2016 mov-ы составляли почти половину компилятора.

Самые первые версии LLVM, до появления clang, выпускались ещё и с бинарниками для SPARC. Потом поддержка SPARC утратила актуальность, и вновь она появилась лишь через 14 лет — с на порядок увеличившимся числом nop-ов:
Сколько инструкций процессора использует компилятор? - 8

Исторически следующая ISA, для которой выпускались бинарники LLVM — это PowerPC: сначала для Mac OS X и затем, после десятилетнего перерыва, для RHEL. Как видно из графика, переход после этого перерыва к 64-битному варианту ISA сопровождался заменой большинства lwz на ld, и вдобавок удвоением разнообразия инструкций:
Сколько инструкций процессора использует компилятор? - 9

В бинарниках для x86_64 и ARM частота использования разных инструкций почти не изменялась:
Сколько инструкций процессора использует компилятор? - 10

Сколько инструкций процессора использует компилятор? - 11

При подсчёте инструкций ARM я отсекал суффиксы условий [8] — вместе с ними получалось около тысячи разных инструкций, но даже и без них ARM сильно опережает другие ISA по разнообразию генерируемых инструкций. Таким образом, слой b на этом графике включает и все условные переходы тоже. Для остальных ISA, где условными могут быть только переходы и немногие другие инструкции, суффиксы условий при подсчёте не отсекались.

Наконец, самая недавняя ISA, для которой публикуются официальные бинарники — это AArch64. Здесь интересно то, что orr с прошлого года почти перестала использоваться:
Сколько инструкций процессора использует компилятор? - 12

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