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

Ответы [ 5 ]

5 голосов
/ 06 мая 2009

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

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

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

v1 = a * b
c = v1 + v1

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

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

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

5 голосов
/ 06 мая 2009

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

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

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

3 голосов
/ 06 мая 2009
  1. Я полагаю, что многие компиляторы используют SSAPRE (Устранение частичного избыточного статического одиночного назначения) для устранения повторяющихся выражений. Для этого требуется, чтобы код находился в форме SSA , что позволяет проводить еще большую оптимизацию.

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

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

1 голос
/ 08 мая 2009

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

0 голосов
/ 30 июля 2009

Вы ищете устранение частичной избыточности (PRE). И CSE (из других ответов), и движение с инвариантным циклом кодируются как PRE. (Разновидностью PRE является Lazy Code Motion, который я считаю оптимальным).

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

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

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

EDIT:

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

...