10. НЕПОЛНОЕ СПАРИВАНИЕ
=======================
Есть ситуации, когда две спаривающиеся инструкции не выполняются одновременно,
а с небольшим перекрытием. Однако они все еще составляют пару, поскольку одна
инструкция выполнятеся в U-трубе, а вторая в V-трубе. Ни одна инструкция не
может начать исполняться, пока не завершаться обе недоспарившиеся инструкции.
Неполное спаривание произойдет в следующих случаях:
10.1 Если у вторых инструкций остановка AGI
10.2 Две инструкции не могут получить доступ к одному и тому-же двойному слову
одновременно.
Следующий пример подоразумевает, что ESI делиться на 4:
MOV AL, [ESI] / MOV BL, [ESI+1]
Два операнда в пределах одного и того-же DWORD, они не могут выполниться
одновременно. На пару уходит 2 такта.
MOV AL, [ESI+3] / MOV BL, [ESI+4]
Здесь два операнда находятся по разные границы DWORD, они спариваются и
на выполнение пары требуется один такт.
10.3 Правило 10.2 распространяется на те данные у которых одинаковые 2-4 бит
в адресах. (конфликт банков кеша) Для DWORD адресов это означает, что
два адреса не должны делиться на 32.
Примеры:
MOV [ESI], EAX / MOV [ESI+32000], EBX ; неполное спаривание
MOV [ESI], EAX / MOV [ESI+32004], EBX ; полное спаривание
Спаренные инструкции, не обращающиеся к памяти выполняются за один такт. MOV
инструкции, передающие данные в или из памяти, так же исполняются за такт,
если данные находятся в кеше и правильно выравнены. Нет замедления при
использовании комплексов режимов адресации, таких как например масштабирование
индексных регистров.
Спаренные инструкции, которые читают из памяти, делают расчеты и сохраняют
результат в регистре флагов, будут исполняться 2 такта.(инструкции
чтения/модифицирования).
Спаренные инструкции, которые читают из памяти, делают расчеты и сохраняют
результат в памяти, будут исполняться 3 такта. (инструкции
чтения/модифицирования/записи).
10.4 Если инструкции чтения/модифицирования спаривается с инструкцией
чтения/модифицирования или чтения/модифицирования/записи, то спаривание
не полное.
Количество используемых тактов приведено в этой таблице:
| Первая инструкция
| MOV или чтение/ чтение/модификация/
Вторая инструкция | межрегистровая модификация запись
----------------------|----------------------------------------------
MOV или межрегистровая| 1 2 3
чтение/модификация | 2 2 4
чтение/мод./запись | 3 3 5
----------------------|-----------------------------------------------
Примеры:
ADD [mem1], EAX / ADD EBX, [mem2] ; 4 такта
ADD EBX, [mem2] / ADD [mem1], EAX ; 3 такта
10.5 Когда спаренные инструкции используют дополнительные такты, из-за
промахов кеша, рассогласования, или не правильного предсказания перехода,
они будут выполняться больше времени, чем каждая инструкция в
отдельности, но потрачено тактов все равно будет меньше, чем если бы
они исполнялись отдельно.
Что бы избежать не полного спаривания, вы должны следить какие инструкции
попадают в U-трубу, а какие в V-трубу. Вы можете просмотреть ваш код, что бы
обнаружить неспариваемые инструкции, инструкции спариваемые только в одной
трубе, или инструкции, которые не могут спариться по правилам, определенным в
разделе 8.
От неполного спаривание можно избавиться просто поменяв инструкции местами.
Например:
L1: MOV EAX,[ESI]
MOV EBX,[ESI]
INC ECX
Здесь инструкции MOV образуют не полную пару, поскольку получают доступ к
одной и той же позиции памяти, последовательность исполнится за 3 такта. Мы
может улучшить код простым переставлением инструкции INC ECX, что бы она
составила пару с одной из инструкций MOV.
L2: MOV EAX,OFFSET [A]
XOR EBX,EBX
INC EBX
MOV ECX,[EAX]
JMP L1
Инструкции INC EBX / MOV ECX,[EAX] спариваются не полно, потому что у
последней - остановка AGI. Последовательность исполниться за 4 такта. Но если
мы вставим инструкцию NOP, или любую подобную, то MOV ECX,[EAX] спариться с
JMP L1, и последовательность выполниться за 3 такта.
Следующий пример - 16 битный, допускается, что SP делиться на 4:
L3: PUSH AX
PUSH BX
PUSH CX
PUSH DX
CALL FUNC
Здесь инструкции PUSH образуют две не полные пары, т.к. оба операнда находятся
по одну границу DWORD. PUSH BX мог бы спариться с PUSH CX, потому что они по
разные границы DWORD, но не делает этого, потому что уже спарился с PUSH AX.
Последовательность исполняется 5 тактов. Но если мы вставим NOP, или
аналогичную инструкцию, то PUSH BX спариться с PUSH CX, а PUSH DX с CALL FUNC.
И тогда последовательность будет выполняться за 3 такта. Другим решением этой
проблемы является - не допуск SP быть делимым на 4. Однако эту проблему трудно
решить в 16 битном режиме, по этому этот способ больше подходит для 32 битного
режима.
Дальше
|