Устранение мертвого кода

редактировать

В теории компиляторов, устранение мертвого кода (также известное как DCE, удаление мертвого кода, удаление мертвого кода или удаление мертвого кода ) - это оптимизация компилятора для удаления кода, который не влияет на результаты программы. Удаление такого кода имеет несколько преимуществ: оно уменьшает размер программы, что является важным соображением в некоторых контекстах, и позволяет запущенной программе избегать выполнения нерелевантных операций, что сокращает время ее выполнения. Он также может обеспечить дальнейшую оптимизацию за счет упрощения структуры программы. Мертвый код включает в себя код, который никогда не может быть выполнен (недостижимый код ), и код, который влияет только на мертвые переменные (записываются, но никогда не читаются снова), которые не имеет отношения к программе.

Содержание

  • 1 Примеры
  • 2 Динамическое устранение мертвого кода
  • 3 См. Также
  • 4 Ссылки
  • 5 Дополнительная литература
  • 6 Внешние ссылки

Примеры

Рассмотрим следующий пример, записанный в C.

int foo (void) {int a = 24; int b = 25; / * Присваивание мертвой переменной * / int c; с = а * 4; return c; b = 24; / * Недостижимый код * / return 0; }

Простой анализ использования значений показал бы, что значение bпосле первого присваивания не используется внутри foo. Кроме того, bобъявлен как локальная переменная внутри foo, поэтому его значение нельзя использовать за пределами foo. Таким образом, переменная bне работает, и оптимизатор может освободить место для хранения и исключить ее инициализацию.

Кроме того, поскольку первая инструкция возврата выполняется безоговорочно, ни один из возможных путей выполнения не достигает второго присвоения b. Таким образом, назначение недоступно и может быть удалено. Если у процедуры был более сложный поток управления , такой как метка после оператора return и gotoв другом месте процедуры, то возможный путь выполнения мог бы существовать для присвоения b.

Кроме того, даже несмотря на то, что в функции выполняются некоторые вычисления, их значения не сохраняются в местах, доступных за пределами области этой функции. Кроме того, учитывая, что функция возвращает статическое значение (96), ее можно упростить до значения, которое она возвращает (это упрощение называется сворачиванием констант ).

Большинство продвинутых компиляторов имеют опции для активации удаления мертвого кода, иногда на разных уровнях. Более низкий уровень может удалять только те инструкции, которые не могут быть выполнены. Более высокий уровень также может не резервировать место для неиспользуемых переменных. Однако более высокий уровень может определять инструкции или функции, которые не служат цели, и устранять их.

Обычно удаление мертвого кода используется как альтернатива дополнительному включению кода через препроцессор . Рассмотрим следующий код.

int main (void) {int a = 5; int b = 6; int c; с = а * (b / 2); if (0) {/ * DEBUG * / printf ("% d \ n", c); } return c; }

Поскольку выражение 0 всегда будет оцениваться как false, код внутри оператора if никогда не может быть выполнен, а удаление мертвого кода полностью удалит его из оптимизированной программы. Этот метод часто используется в отладке для необязательной активации блоков кода; использование оптимизатора с устранением мертвого кода устраняет необходимость использования препроцессора для выполнения той же задачи.

На практике большая часть мертвого кода, который находит оптимизатор, создается другими преобразованиями в оптимизаторе. Например, классические методы для уменьшения силы оператора вставляют новые вычисления в код и делают устаревшие и более дорогие вычисления мертвыми. Последующее удаление мертвого кода удаляет эти вычисления и завершает эффект (без усложнения алгоритма уменьшения силы).

Исторически устранение мертвого кода выполнялось с использованием информации, полученной из анализа потока данных. Алгоритм, основанный на статической форме однократного назначения (SSA) , появляется в оригинальной журнальной статье о форме SSA, написанной Роном Ситроном и др. Роберт Шиллингсбург (он же Шилльнер) усовершенствовал алгоритм и разработал сопутствующий алгоритм для удаления бесполезных операций потока управления.

Динамическое устранение мертвого кода

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

Однако на практике часто бывает, что разделы кода представляют мертвый или недоступный код только при определенных условиях, которые могут быть неизвестны во время компиляции или сборки. Такие условия могут быть наложены разными средами выполнения (например, разными версиями операционной системы или разными наборами и комбинациями драйверов или служб, загруженных в конкретной целевой среде), что может потребовать различных наборов особых случаев. в коде, но при этом становятся условно мертвым кодом для остальных случаев. Кроме того, программное обеспечение (например, драйвер или резидентная служба) может быть конфигурируемым для включения или исключения определенных функций в зависимости от предпочтений пользователя, делая неиспользуемые части кода бесполезными в конкретном сценарии. Хотя модульное программное обеспечение может быть разработано для динамической загрузки библиотек только по запросу, в большинстве случаев невозможно загрузить только соответствующие подпрограммы из конкретной библиотеки, и даже если это будет поддерживаться, подпрограмма может все же включать разделы кода, которые могут считаться мертвым кодом в данном сценарии, но не может быть исключен уже во время компиляции.

Методы, используемые для динамического обнаружения спроса, выявления и разрешения зависимостей, удаления такого условно мертвого кода и рекомбинации оставшегося кода при load или runtime, называются динамическое устранение мертвого кода или динамическое устранение мертвых инструкций .

Большинство языков программирования, компиляторов и операционных систем не предлагают или почти не поддерживают больше, чем динамическая загрузка библиотек и поздняя связывание, поэтому программное обеспечение, использующее динамическое устранение мертвого кода, очень редко используется в сочетании с языками , скомпилированными заранее или написанными на языке ассемблера. Однако языковые реализации, выполняющие своевременную компиляцию, могут динамически оптимизироваться для устранения мертвого кода.

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

См. также

Ссылки

Дополнительная литература

Внешние ссылки

Последняя правка сделана 2021-05-17 04:56:27
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте