Генерация высококачественного кода для программ, написанных на СИ - [7]

Шрифт
Интервал

¦} pop SI ¦

¦ leave ¦

¦ ret ¦

¦ ¦

¦ --> dummy push BP dummy inc AX <-¬(13)¦

¦ ¦ mov BP,SP ret <-- ¦

¦ (28)¦ mov AX,[BP+4] ¦

¦ ¦ inc AX ¦

¦ ¦ leave ¦

¦ L-> ret ¦

+-------------------------------------------------------------+

¦ Подобно большинству компиляторов Си Microsoft C 5.0 ¦

¦ передает параметры функциям путем засылки их в стек. ¦

¦ Всякий раз при вызове выполняется заголовок, так как ¦

¦ функция должна установить адресацию базирующихся на стеке ¦

¦ параметров. Однако компилятор WATCOM C 6.0 удаляет ¦

¦ стековый заголовок благодаря передаче в регистрах стольких ¦

¦ параметров, сколько возможно. ¦

L--------------------------------------------------------------

Большинство компиляторов Си позволяют пользователю указывать, какой набор команд процессора должен использоваться при генерации кода. Хотя специализированные инструкции конкретного процессора и могут ускорить выполнение программы, но их применение может ограничить количество машин, на которых программа может работать.

В случае, когда скорость является критическим параметром, "замена вызова функции ее телом" может помочь в удалении заголовков вызова функций. Некоторые компиляторы предоставляют возможность заменять операторами вызовы функций из некоторого набора, либо генерировать их вызовы. Набор таких функций содержит некоторые общеупотребительные функции, такие как abs. Функции из этого набора называются встроенными. Эта оптимизация полезна для внутренних циклов, которые выполняются многократно. Набор доступных встроенных функций зависит от компилятора.

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

При трансляции условных операторов генератор кода компилятора иногда генерирует инструкции перехода, которые передают управление на другие инструкции перехода. "Сжатие цепочки переходов" просто превращает связанное множество переходов в единственный переход от начала цепочки переходов к конечной цели.

Оптимизировать или нет?

Оптимизация - не панацея, и ее применение не бесплатно. В зависимости от степени оптимизации время, требуемое для компиляции программы, может значительно возрастать. Для небольших программ требуемое время можно не принимать во внимание, но для больших оно может иметь значение.

Оптимизация также может усложнить отладку вследствие генерации кода, который трудно непосредственно связать с исходными операторами в программе. Оптимизация может неожиданно ввести ошибки в код, сгенерированный из вполне правильного текста программы. Ситуация, когда на переменную ссылаются как непосредственно по имени, так и посредством одного или нескольких указателей, может затруднить работу компилятора по определению того, "жива" ли еще переменная и, следовательно, должна оставаться в регистре, или она "умерла" и тогда должна быть сохранена в памяти.

Вынесение инвариантного кода может быть потенциальным источником ошибок. В цикле

>int a[10], x, y;

>for(i = 0; i < 10; i++)

> if( y != 0 )

> a[i] = x / y;

оптимизирующий компилятор может определить, что выражение x/y есть инвариант, и вынесет его за пределы цикла, игнорируя проверку на 0 и создавая возможность возникновения ситуации деления на 0.

Когда компилятор выполняет удаление переменных индукции цикла он может непреднамеренно породить ситуацию переполнения, потому что он может переструктурировать вычисления, включающие индексы цикла. В приведенном ранее примере, где выполняется оптимизация, используя вынесение инвариантного кода и удаление переменных индукции цикла, переменная индукции i была извлечена, в результате имеем:

>T1 = j + k;

>for(x = 0; x < T1 * v; x += T1);

В этом случае, поскольку значения j, k и v неизвестны, существует возможность переполнения для выражения T1 * v. Цикл может не закончиться.

Тестирование компиляторов

PC Tech Journal разработал тест оптимизации Си (см. листинг 1) как подспорье в оценке оптимизационных возможностей компиляторов Си. Тест проверяет степень оптимизации, проводимой компилятором. Для обеспечения основы для сравнения измерений времени выполнения для каждого компилятора запускался тест исполнения PC Tech Journal с ключами, разрешающими оптимизацию. Результаты его работы для каждого компилятора суммируются в таблице 1. Рисунок 6 демонстрирует опции оптимизации для каждого компилятора, которые использовались при компиляции обоих тестов. Характеристики выполнения программ можно сравнить с измерениями без оптимизации, приведенными в февральском номере за 1988 год (см. стр. 62 и 80).


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Геймдизайн. Рецепты успеха лучших компьютерных игр от Super Mario и Doom до Assassin’s Creed и дальше

Что такое ГЕЙМДИЗАЙН? Это не код, графика или звук. Это не создание персонажей или раскрашивание игрового поля. Геймдизайн – это симулятор мечты, набор правил, благодаря которым игра оживает. Как создать игру, которую полюбят, от которой не смогут оторваться? Знаменитый геймдизайнер Тайнан Сильвестр на примере кейсов из самых популярных игр рассказывает как объединить эмоции и впечатления, игровую механику и мотивацию игроков. Познакомитесь с принципами дизайна, которыми пользуются ведущие студии мира! Создайте игровую механику, вызывающую эмоции и обеспечивающую разнообразие.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.