Вопросы Оптимизации Компилятора

  1. какие способы компилятор устраняет повторяющиеся подвыражения recomputations? Как вы отслеживаете под-выражения? И как вы идентифицируете повторяющиеся?
  2. Помимо использования побитовых операторов, каковы некоторые из методов снижения прочности, используемых общими компиляторами?

5 ответов


  1. Я считаю, что многие компиляторы используют SSAPRE (Static Single Assignment Partial Redundancy Elimination) для устранения повторяющихся выражений. Этого требует кодекс форма SSA, что позволяет еще много оптимизаций.

  2. Я не совсем уверен в этом, но посмотрите на этот список LLVM проходит. LLVM является оптимизирующим ИК для компиляторов, который часто быстрее, чем даже GCC. Существует небольшое объяснение каждого пройти. Если вам нужна дополнительная информация, посмотрите Источник LLVM для этих проходов. Он написан на C++ , но довольно чистый и понятный.

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


для 1 имя оптимизации, которую вы ищете, является общим устранением подвыражения (CSE). В зависимости от вашего представления, это может быть довольно легко. Обычно компилятор будет иметь некоторое промежуточное представление программы, где операции максимально разбиты и линеаризованы. Так, например, выражение c = a * b + a * b может быть разбито на:

v1 = a * b
v2 = a * b
c = v1 + v2

Так вы смогли сделать CSE на очень низком уровне путем искать деятельности с таким же оператором и операнды. Когда вы сталкиваетесь с дубликатом (в этом случае v2), вы заменяете все его экземпляры оригиналом. Таким образом, мы могли бы упростить код выше, чтобы быть:

v1 = a * b
c = v1 + v1

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

в любом случае, вы получаете некоторые основные улучшения, и все, что вам нужно отслеживать, это основные выражения. Вы можете сделать этот шаг дальше и искать арифметические идентификаторы. Например, a * b это то же самое, что b * a. Кроме того,x * (y + z) = x * y + x * z. Это делает вашу оптимизацию более сложной, и неясно, что это даст вам такое значительное улучшение производительности. Анекдотически, большая часть выгоды от оптимизации CSE исходит из адресных вычислений, таких как array доступы, и вам не понадобятся сложные личности, как те, что выше.

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


Я настоятельно рекомендую две печатные ссылки на эти темы:

  1. Расширенный Дизайн И Реализация Компилятора Стивен С. Мучник
  2. создание оптимизирующего компилятора Роберт Морган

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


добавить еще одну книгу в список рекомендаций, проверить "хакера" Генри С. Уоррен. Это отличный сборник методов оптимизации общих операций, таких как преобразование целочисленных делений в умножения.


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

проверить Кит Купер, которые, кажется, очень хорошо описывают приемы.

Do не используйте SSAPRE. AFAIK, это требует определенной формы SSA, известной как HSSA, которая имеет несколько недостатки:

  • ее довольно сложно
  • это требует глобального значения чисел (и так SSAPRE не обеспечивает нумерация, как ожидается, уже существуют).
  • он ничего не предоставляет, если ваш язык не поддерживает указатели на переменные стека (и если это так, прекратите писать свой собственный анализ и используйте LLVM или gcc).
  • gcc некоторое время использовал HSSA, но они отошли от него.
  • LLVM экспериментировал с это, но AFAIK они больше не используют его.

EDIT:

книга Мучника имеет подробное описание, связанное с другим ответом.