
- •Содержание
- •Введение
- •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. Ошибки, допускаемые во время прогона
- •Контрольные вопросы
- •Список литературы
149
Замена сложных операций представляет собой замещение одной операции, занимающей довольно много машинного времени, более быстрой последовательностью.
Пример.
I = LENGTH(S1 || S2)
где S1 и S2 цепочки переменной длины, а || означает конкатенацию. Реализовать конкатенацию цепочек довольно сложно. Предположим, что мы заменяем этот оператор эквивалентным оператором
I = LENGTH(S1) + LENGTH(S2).
Теперь мы дважды выполняем операцию определения длины и один раз сложения. Но эти операции занимают существенно меньше времени, как и конкатенация цепочек.
Другие примеры оптимизации такого типа: замена некоторых умножений сложениями и замена некоторых возведения в степень умножениями. Например С ¬R3 можно заменить последовательностью
С ¬ R*R
C ¬ C*R
это дешевле, чем вызвать подпрограмму вычисленияR3 как ANTILOG(3*LOG(R))
6.3.4.Оптимизация циклов
Цикл в программеэто последовательность участков, которая может выполняться повторно. Часто сложно добиться существенных улучшений в смысле времени выполнения программы, применяя преобразования уменьшающие оценку циклов. Универсальные преобразования, которые мы рассматривали, в именно, удаление бесполезных операторов, исключение избыточных вычислений, размножение констант, замена сложных вычислений, полезны и в применении к циклам. Существует, однако, и другие преобразования, ориентированные специально на циклы. Это вынесение вычислений из циклов, замена дорогих операций в цикле более дешевыми и развертывание циклов.
Для того, чтобы применить эти преобразования, цикл сначала надо выделить из данной программы. В случае цикла DO в Фортране, или промежуточного кода образуемого цикломDO, найти цикл просто. Однако понятие цикла в графе управления более обще. Эти обобщенные циклы в графе называют сильно «связанными областями».
Любой цикл графа управления с единственной точкой входа служит примером сильно связанной области. Однако, и более общие структуры циклов также служат примерами сильно связанных областей.

150
Определение. Пусть F- граф управления, а Y-подмножество его участков. Будем называть Y сильно связанной областью в F, если
1)в Y существует единственный участок (вход), что найдется
путь из начальной вершины графаF в , не проходящий ни через какой другой участок из Y
2) существует путь, не нулевой длины лежащий целиком в Y и ведущий из участка Y в любой другой участок в Y.
Пример. Рассмотрим абстрактный граф управления рис. 11.16.
1
2
3
4
7
5
6
Рис. 11.16. Граф управления.
{2,3,4,5}- сильно связанная область с входом 2 {4}- сильно связанная область с входом 4 {3,4,5,6}- область с входом 3 {2,3,7}- область с входом 2 {2,3,4,5,6,7}- область с входом 2
Последняя максимальна в том смысле, что любая другая область с входом 2 содержится внутри этой области.
151
Важной особенностью сильно связанной области, благодаря которой она помогает улучшить код, является однозначность определения входного участка.
Теорема. Пусть F-граф управления. Участок в F является входным участком области тогда и только тогда, когда существует такой
участок ¢, что из него есть дуга в и либо доминирует над ¢, ли-
бо совпадает с ¢.
Перемещение кода
Существует несколько преобразований, в которых для улучшения кода можно воспользоваться знанием областей. Одно из важнейших – перемещение кода. Вычисления, не зависящие от области, можно вынести за ее пределы. Пусть внутри некоторой области с одним входом переменные Y и Z не меняются, но есть оператор X¬ Y+Z. Вычисление Y+Z можно переместить в заново образованный участок области, связанный только с входным участком. Все связи вне области, раннее вошедшие во входной участок, теперь идут в новый участок.
Пример.
К=0
DO 3 I=1,1000 3 K=J+1+I+K
Промежуточная программа для этого фрагмента исходной - про граммы может быть такой.
K¬ 0
I ¬ 1
цикл: T ¬ J + 1
S ¬ T + I
K¬ S + K
if I = 1000 goto выход
I ¬ I+1 goto цикл
выход: halt
Граф этой программы приведен на рис. 11.17.

152
K ¬ 0 B1 I ¬ 0
T ¬ J+1 S ¬ T+I K ¬ S+K I =1000?
I ¬ I+1
B2
halt B4
B3
Рис. 11.17. Граф управления.
Из графа видно, что{ 2, 3} область с входом 2. Оператор Т ¬J+1 инвариантен в этой области, так, что его можно перенести на новый участок, как показано на рис. 11.18.
|
|
|
|
|
K ¬ 0 |
|
B1 |
|
|||||||
|
|
|
|
|
I ¬ 0 |
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
B |
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
T ¬ J+1 |
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
2¢ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
S ¬ T+I |
|
B2 |
|
||||||||
|
|
|
|
K ¬ S+K |
|
|
|||||||||
|
|
|
|
I =1000? |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
B4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
halt |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
I ¬ I+1 |
|
|
B3 |
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 11.18. Преобразованный граф управления.