Telegram Group & Telegram Channel
#compiler

Быстрый Switch: таблица адресов 💨

В C++ оператор switch используется для передачи потока управления в разные места в зависимости от значения переменной.
Оператор switch можно представить как соответствие между значениями переменной, и кодом который должен выполниться для каждого значения.

В зависимости от целевой архитектуры, настроек оптимизации, и свойств конкретного switch-оператора, код может сгенерироваться в разном виде. Есть два варианта, какой ассемблер сгенерирует компилятор:
1️⃣ Цепочка последовательных if-ов. Это самый простой путь, потому что switch-оператор всегда представим в этом виде.
2️⃣ Таблица адресов (мой перевод), он же branch table, он же jump table.

Первый вариант неинтересен, он самый простой и самый неоптимизированный. Если в нашем switch 30 штук case-ов, то в худшем случае произойдет 30 (!) последовательных сравнений (цепочка if-ов), прежде чем программа поймет номер нужной инструкции.
На самом деле в таких случаях компиляторы умеют делать а-ля "бинарный поиск", поэтому вероятно будет log_2(30) сравнений в худшем случае 😁

Во втором варианте номер инструкции, куда надо перепрыгнуть, вычисляется в зависимости от значения переменной, в процессе чего не выполнится ни одного сравнения.

Пример switch с таблицей адресов: https://godbolt.org/z/3debYb4vq
В этом примере в switch сравнивается значение enum-а. Для компилятора enum представляется как underlying type. По умолчанию этот тип int, то есть во всех операциях с enum происходит неявная конвертация в int.
Таким образом, можно представить, что это switch по значениям от 0 до 6 включительно.

В примере компилятор сгенерировал метки LBB0_2, LBB0_3, ..., LBB0_8 для каждого соответствующего кода case X.

Также компилятор сделал таблицу LJTI0_0, где лежат адреса этих меток. Вообще "таблица" это громко сказано, это просто наша абстракция.
"Таблица" представляет из себя несколько последовательных 8-байтовых числа, которые являются адресами меток LBB0_2-LBB0_8.
А метка LJTI0_0 указывает на начало последовательности.

Теперь, имея "таблицу адресов", можно вычислить номер инструкции, куда надо прыгать. Если параметр равен 0, то прыгаем по первому адресу таблицы, если 1 - по второму, и так далее.
        lea     rcx, [rip + .LJTI0_0]
movsxd rax, dword ptr [rcx + 4*rax]
add rax, rcx
jmp rax

Отступление: Как известно, метки имеют смысл только для ассемблера. Метка просто условно указывает на позицию в бинарнике (инструкцию или данные). После процесса линковки, когда в один исполняемый файл (бинарник) утрамбуются отдельные объектные файлы, вместо меток появятся нормальные адреса.
        lea     rcx, [rip + 0x012345678]

Таблица адресов может иметь другую реализацию, но такая общая идея. Например, в примере с Википедии для рандомного 8-битного ассемблера, значение переменной прибавляется к регистру счетчика команд (addwf PCL,F), а сразу после этой инструкции находится таблица с goto до нужной инструкции, и счетчик команд укажет на нужный goto.

Компилятор сам определяет, нужна ли таблица адресов. Обычно она используется для "плотных" switch, где есть case X для последовательных значений X. Если в case X поставить рандомные значения, то таблицы не получится - пример на godbolt, будут последовательные if-ы.
Please open Telegram to view this post
VIEW IN TELEGRAM



group-telegram.com/cxx95/73
Create:
Last Update:

#compiler

Быстрый Switch: таблица адресов 💨

В C++ оператор switch используется для передачи потока управления в разные места в зависимости от значения переменной.
Оператор switch можно представить как соответствие между значениями переменной, и кодом который должен выполниться для каждого значения.

В зависимости от целевой архитектуры, настроек оптимизации, и свойств конкретного switch-оператора, код может сгенерироваться в разном виде. Есть два варианта, какой ассемблер сгенерирует компилятор:
1️⃣ Цепочка последовательных if-ов. Это самый простой путь, потому что switch-оператор всегда представим в этом виде.
2️⃣ Таблица адресов (мой перевод), он же branch table, он же jump table.

Первый вариант неинтересен, он самый простой и самый неоптимизированный. Если в нашем switch 30 штук case-ов, то в худшем случае произойдет 30 (!) последовательных сравнений (цепочка if-ов), прежде чем программа поймет номер нужной инструкции.
На самом деле в таких случаях компиляторы умеют делать а-ля "бинарный поиск", поэтому вероятно будет log_2(30) сравнений в худшем случае 😁

Во втором варианте номер инструкции, куда надо перепрыгнуть, вычисляется в зависимости от значения переменной, в процессе чего не выполнится ни одного сравнения.

Пример switch с таблицей адресов: https://godbolt.org/z/3debYb4vq
В этом примере в switch сравнивается значение enum-а. Для компилятора enum представляется как underlying type. По умолчанию этот тип int, то есть во всех операциях с enum происходит неявная конвертация в int.
Таким образом, можно представить, что это switch по значениям от 0 до 6 включительно.

В примере компилятор сгенерировал метки LBB0_2, LBB0_3, ..., LBB0_8 для каждого соответствующего кода case X.

Также компилятор сделал таблицу LJTI0_0, где лежат адреса этих меток. Вообще "таблица" это громко сказано, это просто наша абстракция.
"Таблица" представляет из себя несколько последовательных 8-байтовых числа, которые являются адресами меток LBB0_2-LBB0_8.
А метка LJTI0_0 указывает на начало последовательности.

Теперь, имея "таблицу адресов", можно вычислить номер инструкции, куда надо прыгать. Если параметр равен 0, то прыгаем по первому адресу таблицы, если 1 - по второму, и так далее.

        lea     rcx, [rip + .LJTI0_0]
movsxd rax, dword ptr [rcx + 4*rax]
add rax, rcx
jmp rax

Отступление: Как известно, метки имеют смысл только для ассемблера. Метка просто условно указывает на позицию в бинарнике (инструкцию или данные). После процесса линковки, когда в один исполняемый файл (бинарник) утрамбуются отдельные объектные файлы, вместо меток появятся нормальные адреса.
        lea     rcx, [rip + 0x012345678]

Таблица адресов может иметь другую реализацию, но такая общая идея. Например, в примере с Википедии для рандомного 8-битного ассемблера, значение переменной прибавляется к регистру счетчика команд (addwf PCL,F), а сразу после этой инструкции находится таблица с goto до нужной инструкции, и счетчик команд укажет на нужный goto.

Компилятор сам определяет, нужна ли таблица адресов. Обычно она используется для "плотных" switch, где есть case X для последовательных значений X. Если в case X поставить рандомные значения, то таблицы не получится - пример на godbolt, будут последовательные if-ы.

BY C++95


Warning: Undefined variable $i in /var/www/group-telegram/post.php on line 260

Share with your friend now:
group-telegram.com/cxx95/73

View MORE
Open in Telegram


Telegram | DID YOU KNOW?

Date: |

Telegram has become more interventionist over time, and has steadily increased its efforts to shut down these accounts. But this has also meant that the company has also engaged with lawmakers more generally, although it maintains that it doesn’t do so willingly. For instance, in September 2021, Telegram reportedly blocked a chat bot in support of (Putin critic) Alexei Navalny during Russia’s most recent parliamentary elections. Pavel Durov was quoted at the time saying that the company was obliged to follow a “legitimate” law of the land. He added that as Apple and Google both follow the law, to violate it would give both platforms a reason to boot the messenger from its stores. Meanwhile, a completely redesigned attachment menu appears when sending multiple photos or vides. Users can tap "X selected" (X being the number of items) at the top of the panel to preview how the album will look in the chat when it's sent, as well as rearrange or remove selected media. Elsewhere, version 8.6 of Telegram integrates the in-app camera option into the gallery, while a new navigation bar gives quick access to photos, files, location sharing, and more. In 2018, Russia banned Telegram although it reversed the prohibition two years later. The Securities and Exchange Board of India (Sebi) had carried out a similar exercise in 2017 in a matter related to circulation of messages through WhatsApp.
from kr


Telegram C++95
FROM American