ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.


Как заблокировать страницу сайта как заблокировать определенные страницы.

 

Часть 7

                                                 549
          EПриложение G. Оптимизация кодаF
    Процессор i486  совместим  по коду и по данным с
процессорами 386(TM) DX и SX.  Были добавлены  всего
лишь  три  команды уровня прикладного программирова-
ния,  которые полезны в специальных ситуациях. Любая
существующая  прикладная  программа  для  процессора
8086/8088,  80286 и 386 может быть выполнена на про-
цессоре  i486 немедленно,  без всякой дополнительной
модификации и перекомпиляции.  Любой компилятор, ко-
торый  генерирует код для процессоров семейства 386,
будет также генерировать код,  который будет  выпол-
няться  на  процессоре i486 без какой-либо модифика-
ции.
    Тем не менее,  сушествует несколько способов оп-
тимизации кода,  которые сделают выполнение приклад-
ных  программ на процессоре i486 более быстрым,  при
помощи всего лишь минимальных изменений  или  вообще
безо  всяких  изменений по отношению к их реализации
для процессоров 386 DX или SX,  за исключением, быть
может,  различий в размере кода. Эти способы следует
применять по отношению к  выбору  последовательности
команд  и командам управления для того,  чтобы полу-
чить преимущества встроенного модуля  режима  конве-
йерной обработки процессора i486 и большой кэш-памя-
ти, расположенной на одной микросхеме.
     G.1. Режимы адресации
    Подобно процессору 386,  процессору i486 необхо-
дим дополнительный такт для генерации исполнительных
адресов, когда используется индексный регистр. Более
того,  если  используется  одна индексная компонента
(т.е. одновременно не используются базовый регистр и
индексный регистр),  и нет необходимости в масштаби-
ровании,  более быстрым является  использование  ре-
550
гистра в качестве базового,  а не в качестве индекс-
ного. Например :
mov   eax, [esi]   ; использование esi в качестве базы
mov   eax, [esi*]  ; использование esi в качестве индекса,
                   ; 1 такт дополнительно
    Если используются и база,  и индекс, или исполь-
зуется масштабирование индекса, более быстрым спосо-
бом адресации является использование комбинированно-
го метода,  даже если это и займет один дополнитель-
ный тактовый цикл процессора при выполнении.
    Когда регистр  используется  в  качестве базовой
компоненты, тогда используется дополнительный такто-
вый цикл, если этот регистр являлся приемником в ко-
манде,  непосредственно выполнявшейся  перед  данной
командой (предполагается, что все операции уже нахо-
дятса в предварительно созданной  очереди).  Поэтому
для получения наибольшего быстродействия две команды
должны разделяться по крайней мере еще одной  коман-
дой. Например:
add   esi, eax    ; esi - регистр-приемник
mov   eax, [esi]  ; esi - базовый регистр, 1 такт
                          дополнительно
    Существуют также  и другие неявные или косвенные
методы использования приемника и базового  регистра,
в  первую очередь регистра указателя стека ESP.  Ре-
гистр ESP является неявной базой  всех  команд  типа
PUSH/POP/RET  и  он же является неявным приемником в
командах CALL/ENTER/LEAVE/RET/ PUSH/POP. Более того,
команда LEAVE, следующаа непосредственно за командой
RET, будет использовать один дополнительный цикл. Но
если  команды LEAVE и RET реорганизованы таким обра-
зом, что одну от другой отделяет какая-то другая ко-
манда,  не  требуется никаких дополнительных тактов.
(Смотри также другие рекомендации, касающиеся коман-
ды LEAVE).
    Нет никакой необходимости  разделять  последова-
                                                 551
тельные  команды PUSH/POP.  Процессор i486 допускает
такую последовательность без использования  дополни-
тельного такта.
    Все такие преобразования последовательности  ко-
манд  не  влияют на выполнение программы на 386 про-
цессоре.
    Процессор i486   также  требует  дополнительного
такта для выполнения команды, которая имеет одновре-
менно и операнд - непосредственное значение,  и опе-
ранд, заданный как смещение в памяти.
    Например :
mov указатель на двойное слово foo, 1234h ;
одновременно и непосредственное значение, и операнд-;
смещение в памяти.
mov указатель на двойное слово baz, 1234h
mov [ebp-200], 1234h
    Когда требуется  использовать  константы,  более
эффективно  использовать  непосредственные  значения
констант вместо предварительной загрузки констант  в
регистры. Но если одна и та же константа использует-
ся больше,  чем один раз, то быстрее будет загрузить
значение  этой константы в регистр и затем много раз
использовать этот регистр. Эта оптимизация не влияет
на выполнение программы на 386 процессоре. Следующая
последовательность действий выполняется быстрее, чем
приведенная выше, если все команды находятся в пред-
варительно созданной очереди,  и,  поскольку команды
короче,  их  в действительности легче организовать в
очередь :
mov eax, 1234h
mov указатель на двойное слово foo, eax
mov указатель на двойное слово baz, eax
mov [ebp-200], eax
552
     G.2 Модуль предварительной выборки
    Модуль предварительной выборки  процессора  i486
получает   доступ   к  расположенной  на  микросхеме
кэш-памяти для того, чтобы заполнить предварительную
очередь команд в тот момент, когда кэш-память не за-
действована для работы и имеется достаточно места  в
очереди для размещения другой строки кэша (16 байт).
Если предварительная  очередь  команд  пуста,  может
потребоваться  три  дополнительных такта для запуска
новой команды.  Предварительная очередь команд зани-
мает 32 байта (2 строки в кэш-памяти).
    Так как доступ к данным всегда имеет высший при-
оритет  по  сравнению с запросами на предварительную
выборку, поддержание кэш-памяти в состоянии занятос-
ти  при  помощи доступа к данным может заблокировать
модуль предварительной выборки.
    Более того, важно организовать команды таким об-
разом, чтобы не использовалась постоянно шина памяти
путем  последовательности команд обращения к памяти.
Команды должны быть  реорганизованы  таким  образом,
чтобы  имелась  команда,  не  обращающаяся  к памяти
(например, команда работы регистр/регистр), по край-
ней  мере  за два такта до того,  как предварительно
сформированная  очередь  команд  станет  исчерпаной.
    Например :
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДї
і         Команда          і      Длина            і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДґ
і  mov  память, 1234567h   і   10  байт            і
і  mov  память, 1234567h   і   10  байт            і
і  mov  память, 1234567h   і   10  байт            і
і  mov  память, 1234567h   і   10  байт            і
і  add  регистр, регистр   і    2  байта           і
АДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДЩ
                                                 553
    Если предварительно  сформированная  очередь ко-
манд полна на момент начала работы,  тогда после вы-
полнения  третьей  команды MOV появляется достаточно
пространства для другой строки кэша в  очереди,  но,
так  как  шина памяти продолжает постоянно использо-
ваться, нет необходимого времени для того, чтобы пе-
редать  строку  из кэша в предварительно формируемую
очередь команд. Если перед или после третьей команды
MOV  не  будет вставлена команда,  не обращающаяся к
памяти,  очередь будет исчерпана четвертой  командой
MOV. В этом случае команды должны быть реорганизова-
ны таким образом, чтобы команда ADD была расположена
до  или после третьей команды MOV,  для того,  чтобы
разрешить кэш-памяти переслать  очередную  командную
строку в модуль предварительной выборки.
    Ни одна из подобных реорганизаций команд не  бу-
дет  оказывать  влияния на скорость выполнения прог-
раммы на процессоре 386 DX.
     G.3 Выравнивание кэша и кода.
    При работе на процессоре 386 приемник  любой  из
команд  JUMP/CALL/ RET должен быть выровнен по адре-
су,  кратному 4, это помогает модулю предварительной
выборки команд в формировании предварительной очере-
ди команд со всей допустимой быстротой,  так как вы-
борка  выполняется  по 4 байта за одно обращение при
выровненных границах.  Так как  на  процессоре  i486
имеется  кэш-память  на микросхеме,  любая предвари-
тельная выборка команд будет выбирать  16  байт  для
заполнения  строки  кэша.  По этой причине наилучшее
быстродействие может быть достигнуто путем  выравни-
вания  операндов-приемников в командах JUMP/CALL/RET
по адресам, кратным 16.
    Однако выравнивание по адресам,  кратным 16, яв-
ляется причиной увеличения размеров кода,  и поэтому
важен компромисс между скоростью выполнения и разме-
рами кода.
554
    Более того,  рекомендуется, чтобы только входные
адреса функций (т.е.,  приемники команд  CALL)  были
выровнены по адресам, кратным 16; в то время как все
метки (т.е. приемники в командах JUMP) продолжали бы
оставаться выровненными по адресам, кратным 4.
    На процессоре i486  требуется  дополнительно  до
пяти тактов для начала выполнения команды,  если она
разбивается более чем на две 16-байтные строки кэша.
Например,  если команда CALL заканчивается на адресе
0x0000000Е и следом за ней  идет  команда  умножения
байтов,  тогда  по возвращении из выполнения команды
CALL  процессор  должен  использовать  дополнительно
пять тактов для того, чтобы заполнить предварительно
формируемую очередь команд,  если только целевая ко-
манда уже не находится в кэше. Даже если целевая ко-
манда уже находится в кэше, тем не менее потребуется
дополнительные 2 цикла для того,  чтобы переслать ее
в модуль предварительной выборки команд.
    Поэтому, если  компилятору известно выравнивание
приемника,  тогда будет быстрее включить команды за-
полнения так, чтобы команда умножения байтов начина-
лась с выровненного адреса.
    Это может быть достигнуто либо путем перестанов-
ки последовательности команд, либо включением коман-
ды NOP.
    Такое выравнивание  команд будет также влиять на
скорость выполнения на процессоре 386.
     G.4. Команда NOP
    Иногда программам  необходим  заполнитель  между
командами для того, чтобы выравнивать их. На процес-
сорах 386 и i486 таковым заполнителем является одно-
байтовая команда NOP, которая в действительности об-
менивает содержимое регистра ЕАХ  с  содержимым  ре-
гистра ЕАХ же.
                                                 555
    Команды других длин могут быть выполнены за один
цикл. Таблица ниже приводит некоторые из них.
1-байная  inc регистр             ;модифицирует регистр и
                                  ;флаги
2-байтная mov регистр, регистр    ;в действительности NOP
3-байтная lea регистр, 0[регистр] ;в действительности NOP,
                                  ;с использованием
                                  ;8-разрядного смещения
5-байтная mov eax, 0              ;модифицирует регистр eax
5-байтная add eax, 0              ;модифицирует флаги
6-байтная lea reg, 0[eax]         ;в действительности NOP,
                                  ;с использованием
                                  ;32-разрядного смещения
    Вдобавок, многие  команды  процессоров  386/i486
имеют особые формы и длины,  использующие непосредс-
твенные данные различной длины или смещения в памяти
различной размерности. Также некоторые команды имеют
укороченные формы, если операндом-приемником являет-
ся регистр EAX/AX/AL.
    Не все команды с различными формами будут выпол-
няться за одно и тоже  время.  Примером,  в  котором
различные  формы будут выполняться за различное вре-
мя,  являются команды PUSH/POP/REG. Если они закоди-
рованы  в однобайтовую форму,  они будут выполняться
за один цикл,  но если они закодированы в  2-байтную
форму, они будут выполняться за 4 цикла.
    Команды заполнения NOP будут  также  выполняться
быстрее,  чем  команда XCHG на процессорах семейства
386. Использование различных форм одной и той же ко-
манды  не влияет на быстродействие при выполнение на
процессоре 386.
                                                 555
     G.5. Команды работы с целыми числами
    Процессор i486 может выполнять большинство часто
используемых команд (таких, как загрузка или запоми-
нание регистра, АЛУ-операции с регистром, и т.д.) за
один такт.  Однако, в отличие от процессора 386, не-
которые из операций с памятью занимают теперь больше
циклов,  чем  соответствующие операции с регистрами.
Например, команда PUSH MEM :
P      ЪДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДД
ДДДї
      і    Команда       іТакты ЦПУ 386(ТМ) DXіТакты ЦПУ i486(TM)
      ГДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДД
      іmov регистр,памятьі          4         і         1        
      іpush регистр      і          2         і         1        
      іpush память       і          5         і         4        
      АДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДД
ЩM
    Tаким образом,  для  процессора  i486,  загрузка
значения из памяти в регистр и затем занесение этого
регистра в стек приведет к чистому сохранению 2 так-
тов;  но для процессора 386 DX таже самая последова-
тельность команд приведет  к  чистой  потере  одного
такта.  Однако для того,  чтобы загрузить значение в
регистр на процессоре i486,  необходимо найти пустой
регистр;  если действие по загрузке значения уничто-
жит значение регистра,  которое могло быть использо-
вано позднее,  то сохранение значения может привести
к отрицательному результату по причине  потери  пов-
торно используемого значения регистра.
    Другим примером служит команда LEAVE :
P       ЪДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДД
ДДї
       і     Команда і Такты ЦПУ 386(ТМ) DX іТакты ЦПУ i486(TM) і
       ГДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДґ
       іmov esp, ebp і           2          і         1         і
       іpop ebp      і           4          і1+1 (штраф за esp) і
       іleave        і           4          і         5         і
       АДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДЩ
M
556
    Опять же, для процессора i486, выполнение после-
довательности команд MOV/POP приводит к чистому сох-
ранению 2 тактов по сравнению с командой LEAVE; в то
время,  как выполняясь на процессоре 386 DX, команда
LEAVE одновременно и быстрее,  и короче. Однако, так
как  первая команда MOV использует регистр ESP в ка-
честве приемника и команда POP также неявно  исполь-
зует  регистр  ESP в качестве базы (как уже упомина-
лось выше), эта последовательность действий приводит
к получению одного штрафного такта,  если только две
команды не разделены другой командой.  Если возможно
таким образом переупорядочить команды, чтобы команды
MOV/POP были бы разделены полезной  командой,  тогда
чистый  выигрыш  в  тактах  по  сравнению с командой
LEAVE составил бы 3 такта на процессоре i486.
    Так как  процессор i486 может работать с операн-
дами в регистрах быстрее,  чем с операндами в памяти
(как  и почти большинство других архитектур),  важно
иметь хорошее  размещение  регистров  и  оптимизацию
трекинга значений в любом из компиляторов.  С другой
стороны,  нет сохранения при загрузке каждого значе-
ния перед его использованием, как это сделано в RISC
архитектуре.  Процессор i486 может выполнять команды
АЛУ типа регистр,память также быстро, как и последо-
вательности   команд   загрузить/операция/запомнить.
Например,  для присваивания: память1 = память1 + па-
мять2 - можно использовать следующие  последователь-
ности команд, с варьированием общего количества так-
тов для процессоров 386 DX и SX,  но одним и тем  же
количеством тактов для процессора i486:
P       ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДД
ДДї
       і     Команда    іТакты ЦПУ 386(ТМ) DXіТакты ЦПУ i486(TM)і
       ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДґ
       іmov eax, память1і          4         і         1        і
       іmov ebx, память2і          4         і         1        і
       іadd eax, ebx    і          2         і         1        і
       іmov память1, eaxі          2         і         1        і
       АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДЩ
M
                                                 557
P       ЪДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДД
ДДї
       і     Команда    іТакты ЦПУ 386(ТМ) DXіТакты ЦПУ i486(TM)і
       ГДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДґ
       іmov eax, память1і          4         і         1        і
       іadd память2, eaxі          7         і         3        і
       і                і                    і                  і
       іmov eax, память1і          4         і         1        і
       іadd eax, память2і          6         і         2        і
       іmov память1, eaxі          2         і         1        і
       АДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДЩ
M
    Команда MOVZX является другим примером,  в кото-
ром процессор i486 может работать быстрее с  исполь-
зованием  простых  команд,  если приемником является
регистр,  который в свою очередь может быть адресуем
побайтно. Например, загрузка значения байта:
P      ЪДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДД
ДДДї
      і     Команда      іТакты ЦПУ 386(ТМ) DXіТакты ЦПУ i486(TM)
      ГДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДД
      іmovzx eax, память1і          6         і3+1 (префикс 0Fh) 
      іxor eax, eax      і          2         і         1        
      іmovb al, память1  і          4         і         1        
      АДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДД
ЩM
    Таким образом,   для  процессора  i486,  сначала
очистка регистра и затем загрузка значения  регистра
может  дать  в  качестве  результата чистую экономию
двух тактов (в зависимости от того, где такт декоди-
рования  префикса может быть перекрыт предыдущей ко-
мандой,  смотри Раздел G.8,  посвященный  Префиксным
кодам операций), в то время как нет разницы в выпол-
нении команд на процессоре 386 DX.
     G.6. Коды условия
    В некоторых  языках  программирования   высокого
уровня иногда необходимо преобразовать результат бу-
левского условия (а  именно,  равенства,  больше-чем
558
или  меньше-чем  и  так далее) в значение истина или
ложь (т.е.  0/1).  Процессоры 386 и i486 обычно под-
держивают  результаты  сравнения  в регистре флагов,
поэтому  для  того,  чтобы  преобразовать  результат
сравнения в значение истина/ ложь, необходимо преоб-
разовать значения флагов в целые значения.
    Процессоры 386  и  i486  имеют  множество команд
SETcc, которые выполняют такое преобразование, одна-
ко команды SETcc занимают 3 или 4 такта при выполне-
нии на процессоре i486, в зависимости от того, когда
условие  проверяется на истину или ложность.  Специ-
ально при сравнении значений без знака на больше чем
или меньше чем, имеется необязательная для использо-
вания последовательность  действий.  Например,  если
"x" и "y" являются значениями без знака,  и "x" заг-
ружен в регистр eax и "y" загружен  в  регистр  ecx,
тогда  код  для сравнения "(x




Яндекс цитирования