
- •Содержание
- •Введение
- •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. Ошибки, допускаемые во время прогона
- •Контрольные вопросы
- •Список литературы

37
|
|
|
LOAD |
=0.98 |
|
|
||
|
|
|
STORE $2 |
|
|
|||
|
|
|
LOAD |
TAX |
|
|
||
|
|
|
STORE $1 |
|
|
|||
|
|
|
LOAD |
PRICE |
|
|
||
|
|
n3 |
ADD |
$1 |
|
|
|
|
|
|
|
MPY |
$2 |
|
|
|
|
|
|
|
STORE COST |
|
=0.98 |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STORE $2 |
|
|
|
|
|
|
|
|
LOAD |
TAX |
<ИД1> |
|
|
|
|
n2 |
STORE $1 |
||
|
|
|
|
LOAD |
PRICE |
|||
= |
|
|
||||||
cost |
|
|
|
|
ADD |
$1 |
||
|
|
|
|
|||||
|
|
|
|
|
|
|
MPY |
$2 |
TAX |
|
|
|
|
|
|
|
|
STORE $1 |
|
|
|
|
|
|
||
n1 |
* |
<ИД4> |
|
|||||
LOAD |
PRICE |
|
||||||
ADD |
$1 |
|
|
|
|
|
0.98 |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
||
|
<ИД2> |
+ |
|
<ИД3> |
|
|
||
|
PRICE |
|
|
TAX |
|
|
Рис. 2.4. Дерево с генерированными кодами
2.8. Оптимизация кода
Во многих случаях желательно иметь компилятор, который бы создавал эффективно работающие объектные программы. Термин оптимизация кода применяется к попыткам сделать объектные программы более «эффективными», т.е. быстрее работающими или более компактными.
Для оптимизации кода существует широкий спектр возможностей. На одном конце находятся истинно оптимизирующие алгоритмы. В этом случае компилятор пытается составить представление о функции, определяемой алгоритмом, программа которого записана на исходном языке. Если он «догадается», что это за функция, то может попытаться заменить прежний алгоритм новым, более эффективным алгоритмом, вычисляющий ту же функцию, и уже для этого алгоритма генерировать машинный код.
К сожалению, оптимизация этого типа чрезвычайно трудна, т.к. нет алгоритмического способа нахождения самой короткой или самой быстрой программы, эквивалентной данной.
38
Поэтому в общем случае термин«оптимизация» совершенно неправильный – на практике мы должны довольствоватьсяулучшением кода. На разных стадиях процесса компиляции применяются различные приемы улучшения кода.
В общем случае мы должны выполнить над данной программой последовательность преобразований в надежде повысить ее эффективность. Эти преобразования должны, разумеется, сохранить эффект, создаваемый во внешнем мире исходной программой.
Преобразования можно проводить в различные моменты компиляции, начиная от входной программы, заканчивая фазой генерации кода.
Более подробно оптимизацией кода мы займемся далее.
Сейчас рассмотрим лишь те приемы, которые делают код более коротким.
1) Если + - коммутативная операция, то можно заменить последовательность команд LOAD a; ADD b; последовательностью LOAD b; ADD a. Требуется, однако, чтобы в других местах не было перехода к оператору ADD b.
2)Подобным же образом, если * - коммутативная операция, то можно заменить LOAD a; MPY b на LOAD b; MPY a.
3)Последовательность операторов типа STORE a; LOAD a можно удалить из программы при условии, что либо ячейка a не будет использоваться далее, либо перед использованием ячейка a будет заполнена заново.
4)Последовательность LOAD a; STORE b; можно удалить, если за ней следует другой операторLOAD и нет перехода к оператору STORE b, а последующие вхождения b будут заменены на a вплоть до того места, где появится другой операторSTORE
b.
Рассмотрим наш пример. Мы получили программу (табл. 2.3).