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

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

>if(a == 0)

> a = y * 3;

>else

> b = y * 3;

приводит к логическому эквиваленту:

>T1 = y * 3;

>if(a == 0)

> a = T1;

>else

> b = T1;

Рисунок 1 демонстрирует практический выигрыш от выделения общих подвыражений в реальном коде.

--------------------------------------------------------------¬

¦РИСУНОК 1: Выделение общих подвыражений ¦

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

¦Исходный текст на Си BORLAND LATTICE ¦

¦ Turbo C 1.5 MS-DOS C 3.2 ¦

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

¦if((h3 + k3) < 0 || mov AX,h3 mov AX,h3 ¦

¦ (h3 + k3) > 5) add AX,k3 add AX,k3 ¦

¦ printf("Common\ jl @18 js L0187 ¦

¦ subexpression\ mov AX,h3 cmp AX,5 ¦

¦ elimination"); add AX,k3 jle L0193 ¦

¦ cmp AX,5 L0187: ¦

¦ jle @17 mov AX,01.0000 ¦

¦ @18: push AX ¦

¦ mov AX,offset s@ call printf ¦

¦ push AX add SP,2 ¦

¦ call printf L0193: ¦

¦ mov SP,BP ¦

¦ @17: ¦

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

¦Многократные вхождения вычислений заменяются значением, ¦

¦которое является результатом единственного вхождения ¦

¦вычисления. Borland Turbo C вычисляет значение выделенного ¦

¦выражения h3+k3 дважды, тогда как LATTICE MS-DOS C и другие ¦

¦применяют выделение общих подвыражений и вычисляют ¦

¦выражение только один раз. ¦

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

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

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

>#define DEBUG 0

>if(DEBUG)

> printf("Debug Function\n>");

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

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

>a = 5;

>b = 0;

>a = b;

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

Цель "распределения переменных по регистрам" состоит в попытке обеспечить оптимальное назначение регистров путем сохранения часто используемых переменных в регистрах так долго, как это возможно, для того, чтобы исключить более медленный доступ к памяти. Количество регистров, доступных для использования, зависит от архитектуры процессора. Семейство микропроцессоров Intel 80x86 резервирует много регистров для специального использования и имеет несколько универсальных регистров. В помощь распределению переменных по регистрам язык Си предоставляет спецификатор класса регистровой памяти, который дает возможность программисту указывать, какие переменные должны располагаться в регистрах.

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


Рекомендуем почитать
Графика для Windows средствами DirectDraw

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


Виртуальная библиотека Delphi

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


Пишем драйвер Windows на ассемблере

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


Как писать драйвера

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


MFC и OpenGL

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


Информационная технология. Оценка программной продукции характеристики качества и руководства по их применению

Стандарт подготовлен на основе применения аутентичного текста международного стандарта ИСО/МЭК 9126-91 «Информационная технология. Оценка программной продукции. Характеристики качества и руководства по их применению»Information technology. Software product evaluation. Quality characteristics and guidelines for their use.