Генерация высококачественного кода для программ на СИ - Lattice Inc.
ОГЛАВЛЕНИЕ
Lattice Inc.
Имеющий большую историю компилятор Lattice MS-DOS C последовательно
совершенствовался с каждой новой версией. Он известен как генератор
стабильного, предсказуемого кода и выполняет умеренную оптимизацию.
Lattice С выполняет снижение мощности, сжатие цепочки переходов и удаление
общих подвыражений. Он не удаляет дублирующиеся присваивания после теста
встроенных функций и лишние присваивания в функции dead_code. Хотя он не
генерирует никакого кода для недостижимого printf в функции dead_code,
компилятор Lattice C генерирует ненужный безусловный переход к LEAVE,
которая является следующей инструкцией.
Единственными сгенерированными машинно-зависимыми инструкциями были ENTER
и LEAVE, инструкции микропроцессоров 80x86 для прологов и эпилогов
функций. Это сомнительное благо, поскольку выполнение ENTER требует больше
циклов микропроцессора, чем установка адресации стекового фрейма
отдельными инструкциями. Lattice C не выполняет оптимизацию циклов.
Manx Software Systems Inc.
Компилятор Aztec C86 сгенерировал хороший код с довольно хорошим уровнем
оптимизации. Кроме свертки констант и алгебраических упрощений, Aztec C86
выполнил снижение мощности и удаление общих подвыражений. Однако, он не
выполнил удаление лишних присваиваний и не удалял недостижимый код. Aztec
C86 сгенерировал код для недостижимого оператора printf вместе с
безусловным переходом через него.
Поскольку любая программа на Си имеет значительное количество вызовов
функций, заголовок каждого вызова необходимо минимизировать. Aztec C86
использует необычный, но эффективный подход к решению этой проблемы. На
выходе компилятора получается текст в языке ассемблера, который
обрабатывается отдельным ассемблером. Компилятор вставляет в текст
директивы условного ассемблирования вокруг кода, который устанавливает
стековый фрейм и сохраняет регистры. После генерации кода функции
компилятор определяет символы для управления установкой стекового фрейма и
сохранения только тех регистров, которые используются в функциии.
Aztec C86 не смог решить задачу преобразования цепочки переходов в один
переход к конечной цели. Он также не выполнял оптимизацию циклов.
Metaware Inc.
High C вырабатывает хороший код со средним уровнем оптимизации. Компилятор
выполняет все базовые виды оптимизации, включая свертку констант и
алгебраические упрощения, удаление лишних операций загрузки регистров,
снижение мощности и удаление общих подвыражений. Компилятор Metaware
удаляет недостижимый код из функции dead_code, но не удаляет лишние
присваивания.
High C разумно использует машинно-зависимые инструкции. Компилятор
усовершенствует загрузку констант с плавающей точкой, используя команду
копирования строк MOVS процессоров 80x86 для записи значений с плавающей
точкой, вычисленных во время компиляции. Он также генерирует инструкцию
LEAVE процессоров 80x86 для эпилога функций, но устанавливает адресацию
стекового фрейма в прологе функции с помощью отдельных инструкций, а не
используя более длительную инструкцию ENTER.
Компилятор High C не выполняет вынесение инвариантного кода, важный метод
оптимизации циклов. Он также не смог применить успешно удаление переменных
индукции циклов. Встроенные функции поддерживаются для нескольких
целочисленных и строковых операций, таких как strlen.
Microsoft C.
В версии 5.0 своего компилятора Си корпорация Microsoft вывела высокий
уровень оптимизации кода на рынок PC. Microsoft уделяет много внимания
анализу циклов. C 5.0 - единственный из рассматриваемых компиляторов,
который выполняет вынесение инвариантного кода и настоящее удаление
переменных индукции циклов. Компилятор Microsoft C 5.0 превосходно
использует регистры, стараясь минимизировать обращения к памяти в теле
цикла (см. рис. 4 и 5).
Простой пример цикла в коде теста демонстрирует степень оптимизации
циклов, выполняемой Microsoft C 5.0 (см. рис. 3). Компилятор применяет
снижение мощности и полностью удаляет константное умножение, выявляет
конечное состояние переменных j5 и k5, и помещает в регистры все
переменные внутри цикла.
Другой хороший пример оптимизации циклов этим компилятором отражен в
функции unnecessary_loop. C 5.0 удаляет цикл for и генерирует код только с
целью установки конечного состояния переменной - индекса цикла и
оператора, включенного в цикл. Компилятор также хорошо использует
регистры.
Внимание фирмы Microsoft к оптимизации вознаграждается при работе теста
выполнения. Он выполняется за время, которое является лучшим или близко к
лучшему по каждой категории.