
- •Содержание
- •Введение
- •1.3. Множества цепочек
- •1.4. Языки
- •1.5. Алгоритмы
- •1.6. Некоторые понятия теории графов
- •Контрольные вопросы
- •2. Введение в компиляцию
- •2.1. Задание языков программирования
- •2.2. Синтаксис и семантика
- •2.3. Процесс компиляции
- •2.4. Лексический анализ
- •2.5. Работа с таблицами
- •Переменная с плавающей точкой
- •2.6. Синтаксический анализ
- •2.7. Генератор кода
- •2.8. Оптимизация кода
- •2.8. Оптимизация кода
- •2.9. Исправление ошибок
- •2.10. Резюме
- •Контрольные вопросы
- •3. Теория языков
- •3.1. Способы определения языков
- •3.2. Грамматики
- •3.4. Распознаватели
- •3.5. Регулярные множества, их распознавание и порождение
- •5.2. LR(1) - таблица разбора
- •5.3. Построение LR – таблицы разбора
- •5.4. Сравнение LL – и LR – методов разбора
- •Контрольные вопросы
- •6. Оптимизация кода
- •6.1. Оптимизация линейного участка
- •6.1.1. Модель линейного участка
- •6.1.2. Преобразование блока
- •6.1.3. Графическое представление блоков
- •6.1.4. Критерий эквивалентности блоков
- •6.1.5. Оптимизация блоков
- •6.1.6. Алгебраические преобразования
- •6.2. Арифметические выражения
- •6.2.1. Модель машины
- •6.2.2. Разметка дерева
- •6.2.3. Программы с командами STORE
- •6.2.4. Влияние некоторых алгебраических законов
- •6.3. Программы с циклами
- •6.3.1. Модель программы
- •6.3.2. Анализ потока управления
- •Алгоритм вычисления прямого доминирования
- •6.3.3. Примеры преобразования программ
- •Удаления бесполезных операторов
- •Замена сложных операций
- •6.3.4. Оптимизация циклов
- •Перемещение кода
- •Индуктивное перемещение
- •Замена сложных операций
- •6.4. Анализ потоков данных
- •6.4.1. Интервалы
- •6.4.2. Анализ потоков данных с помощью интервалов
- •6.4.3. Несводимые графы управления
- •7. Включение действий в синтаксис
- •7.1. Получение четверок
- •7.2. Работа с таблицей символов
- •Контрольные вопросы
- •8. Проектирование компиляторов
- •8.1. Число проходов
- •8.2. Таблицы символов
- •8.3. Таблица видов
- •Контрольные вопросы
- •9. Распределение памяти
- •9.1. Стек времени прогона
- •9.2. Методы вызова параметров
- •9.3. Обстановка выполнения процедур
- •9.4. «Куча»
- •9.5. Счетчик ссылок
- •9.6. Сборка мусора
- •Контрольные вопросы
- •10. Генерация кода
- •10.1. Генерация промежуточного кода.
- •10.2. Структура данных для генерации кода
- •10.3. Генерация кода для типичных конструкций
- •10.3.1. Присвоение
- •10.3.2. Условные зависимости
- •10.3.3. Описание идентификаторов
- •10.3.4. Циклы
- •10.3.5. Вход и выход из блока
- •10.3.6. Прикладные реализации
- •10.4. Проблемы, связанные с типами
- •10.5. Время компиляции и время прогона
- •Контрольные вопросы
- •11. Исправление и диагностика ошибок
- •11.1. Типы ошибок
- •11.2. Лексические ошибки
- •11.3. Ошибки в употреблении скобок
- •11.4. Синтаксические ошибки
- •11.5. Методы исправления синтаксических ошибок
- •11.6. Предупреждения
- •11.7. Сообщения о синтаксических ошибках
- •11.8. Контекстно-зависимые ошибки
- •11.9. Ошибки, связанные с употреблением типов
- •11.10. Ошибки, допускаемые во время прогона
- •Контрольные вопросы
- •Список литературы
|
|
115 |
|
X6¬X2*X4 |
|
|
|
X7¬X6*X5 |
|
|
|
X1¬A+B |
|
|
|
X3¬X1*X2. |
|
|
|
LOAD |
A |
LOAD |
B |
ADD |
B |
SUBTR C |
|
STORE X |
STORE X5 |
||
LOAD |
A |
LOAD |
A |
SUBTR B |
SUBTR C |
||
STORE X2 |
STORE X4 |
||
LOAD |
X1 |
LOAD |
A |
MULT |
X2 |
SUBTR |
B |
STORE X3 |
STORE X2 |
||
LOAD |
A |
MULT |
X4 |
SUBTR C |
MULT |
X5 |
|
STORE X4 |
STORE X7 |
||
LOAD |
B |
LOAD |
A |
SUBTR C |
ADD |
B |
|
STORE X5 |
MULT |
X2 |
|
LOAD |
X2 |
STORE |
X3 |
MULT |
X4 |
|
|
MULT |
X5 |
|
|
STORE X7 |
|
|
|
а – из 2 |
б – из 3 |
|
6.1.6.Алгебраические преобразования
Во многих языках программирования некоторые операции и операнды подчиняются определенным алгебраическим законам. Учитывая эти законы, можно проводить такие улучшения программы, какие не-
возможно сделать с использованием четырех рассмотренных выше типов преобразований.
Рассмотрим наиболее распространенные алгебраические преобразования.
1)Бинарная операция q называется коммутативной, если aqb = bqa для всех выраженийa и b. Примером коммутативных операций случат сложение и умножение чисел.
2)Бинарная операция q называется ассоциативной, если aq(bqg)
=(aqb)qg для всех a, b и g. Например сложение коммутативно, так как a+(b+g) = (a+b)+g.
116
3) Бинарная операция q1 называется дистрибутивной относительно бинарной операции q2, если aq1(bq2g) = (aq1b)q2(aq1g). Например, умножение дистрибутивно относительно сложения, так как a*(b+g) = a*b+a*g.
4)Унарная операция q называется идемпотентной, если qqa = a для всех a. Например, логическое не и унарная операция«минус» идемпотентны.
5)Выражение e называется нейтральным относительно бинарной операции q, если eqa = aqe = a для всех a.
(а) Константа 0 нейтральна относительно сложения. Нейтрально и
любое выражение, имеющее значение 0, Например, a - a, a * 0, (-a) + a.
(б) Константа 1 нейтральна относительно умножения.
(в) Логическая константа истина нейтральна относительно конъюнкции (т.е. a Ù истина = a для всех a).
(г) Логическая константа ложь нейтральна относительно дизъюнкции (т.е. a Ú ложь = a для всех a).
Если A – множество алгебраических законов, будем говорить, что
выражение a эквивалентно выражению b относительно A (и писать a ºA b), если a можно преобразовать вb, применяя только алгебраические законы A.
Пример. Рассмотрим выражение
A * (B * C) + (B * A) * D +A * E.
С помощью ассоциативного закона умножения можно записать A*(B*C) в виде (A*B)* C. С помощью коммутативного закона умноже-
ния можно записать B*A в виде A*B. Применяя дистрибутивный закон, все выражение можно записать
(A * B)* (C + D) +A * E.
Наконец, применяя ассоциативный закон к первому слагаемому, затем дистрибутивный закон, можно записать выражение как
(A * (B * (C + D) + E).
Таким образом, это выражение эквивалентно исходному относительно ассоциативного, коммутативного и дистрибутивного законов умножения и сложения. Одного оно вычисляется только двумя умножениями и двумя сложениями, в то время как для исходного требовалось пять умножений и два сложения.
Определение эквивалентности относительно множества алгебраических законов A можно распространить и на блоки. Будем говорить,

117
что блоки 1 и 2 эквивалентны относительно A (и писать 1 ºA 2),
если существует такое выражение b Î v( 2), что a ºA b, и обратно. Пример. Если сложение коммутативно, то преобразование блоков,
соответствующее этому алгебраическому закону, позволяет заменять в блоке оператор вида X ¬ A+B на оператор X ¬ B+A. Соответствующие преобразования графа позволяют заменить всюду в графе структуру
+ |
+ |
на
b |
a |
a |
b |
Если дан конечный набор алгебраических законов и соответствующие преобразования блоков, то для нахождения оптимального блока, эквивалентного данному, желательно было бы применять их вместе с топологическими преобразованиями. К сожалению, для конкретного набора алгебраических законов может не быть эффективного способа применения этих преобразований для нахождения оптимального блока.
Обычный подход к решению этого вопроса заключается в том, что алгебраические преобразования применяют в ограниченном виде, надеясь сделать больше «упрощений» выражений и выработать, возможно, большее число общих подвыражений. В типичной схемеbqa заменяется на aqb, если q - коммутативная бинарная операция, а a предшествует b при некотором лексикографическом упорядочении имен переменных. Если q - ассоциативная и коммутативная бинарная операция, то a1qa2q…qan можно преобразовав, располагая имена a1,…, an в лексикографическом порядке и группирую их слева направо.
Пример. Рассмотрим блок = (P, I, {Y}), где I = {A, B, C, D, E, F}, а P – последовательность операторов
X1 ¬ B-C
X2 ¬ A*X1

118
X3 ¬ E*F
X4 ¬ D*X3
Y ¬ X2*X3
Блок вычисляет выражение
Y = (A * (B – C)) * (D * (E * F)).
Граф для приведен на рис. 11.5.
|
|
* |
|
* |
|
|
* |
A |
- |
D |
+ |
B C E F
Рис. 11.5. Граф для .
Предположим, что для генерируется программа на языке ассемблера и используются введенные нами ранее функции оценки. Приме-
няя к коммутативные и ассоциативные преобразования для умножения проведем последовательное преобразование программы.
Полагая, что умножения ассоциативно, можно заменить два опера-
тора в
X3 ¬ E*F
X4 ¬ D*X3
на три оператор
X3 ¬ E*F
X3¢ ¬ D*E
X4 ¬ X3¢*F
Теперь оператор X3 ¬ E*F бесполезен, и его можно удалить преобразованием T1. Затем с помощью ассоциативного преобразования можно заменить операторы
X4 ¬ X3¢*F
119
Y ¬ X2*X3
на
X4 ¬ X3¢*F
X4¢ ¬ X2* X3¢ Y ¬ X4¢* F
Оператор X4 ¬ X3¢*F теперь бесполезен, и его можно удалить. Таким образом имеем пять операторов
X1 ¬ B-C
X2 ¬ A*X1
X3¢ ¬ D*E X4¢ ¬ X2* X3¢ Y ¬ X4¢* F
Если применить ассоциативные преобразования еще раз к третьему и четвертому оператору, получим
X1 ¬ B-C
X2 ¬ A*X1
X3² ¬ X2*D
X4¢ ¬ X3²*E
Y ¬ X4¢* F
Наконец, если предположить, что умножение коммутативно, мож-
но переставить операнды второго оператора и получить блок ¢:
X1 ¬ B-C
X2 ¬ X1* A
X3² ¬ X2*D
X4¢ ¬ X3²*E
Y ¬ X4¢* F
Граф для ¢ изображен на рис. 11.6. Блок ¢ имеет оценку 7, самую нижнюю возможную оценку для исходной программы.