Может ли какие-либо штрафы при смешивании 32 и 64-битовых регистров размеров в последовательных инструкций?
No, writing to a 32-bit register always zero-extends to the full register, поэтому x86-64 избегает любых штрафов за частичный регистратор для 32-разрядной и 64-разрядной инструкции.
Таким образом, я считаю, что 32 бита по-прежнему являются родными.
Да, размер операнда по умолчанию для большинства инструкций составляет 32 бит (other than PUSH/POP). Для 64-битного кода требуется префикс REX с бит W, установленным в 1. Предпочитают 32-битные причины для кода. Вот почему компиляторы используют mov r32, imm32
для адресов статических данных (поскольку по умолчанию для кодовой модели требуется, чтобы кодовые и статические адреса данных находились в низком виртуальном адресном пространстве 2 Гбит).
Это был дизайнерский выбор от AMD. Они могли выбрать другой путь и потребовали префикс, чтобы получить размер 32-битного операнда. Поскольку длительный режим - это отдельный режим, машинный код x86-64 может отличаться от машинного кода x86-32, но он хочет. AMD решила минимизировать различия, чтобы они могли делиться как можно большим количеством транзисторов в декодерах. Ваш вывод верен, но ваши рассуждения полностью фиктивные.
частичные обновления регистра (например, топор вместо EAX) может вызвать срыв EFLAGS и привести к снижению производительности.
Партии с отдельным флагом отделены от парковых столов с частными регистрами. Они обрабатываются аналогично внутренне (отдельно переименованные части EFLAGS должны быть объединены так же, как модифицированный AX должен быть объединен с немодифицированными верхними байтами EAX). Но один не вызывает другого.
# partial-reg stall
setcc al # leaves the upper 3 (or 7) bytes unmodified
add edx, eax # reads full EAX. Older CPUs stall while merging
Zeroing EAX ahead of the flag-setting and setcc with xor eax,eax
avoids the partial-register penalty entirely. (Core2/Nehalem останавливается на меньшее количество циклов, чем предыдущие процессоры, но все равно останавливается на 2 или 3c при вставке слияния uop.Sandybridge вообще не останавливается при вставке слияния uop).
(Другое резюме штрафов за частичный регистратор на разных ЦП: Why doesn't GCC use partial registers?, говоря в основном то же самое).
AMD не страдает от неполных регистров при чтении полного регистра позже, но вместо этого частичная регистрация записей и чтения имеет ложную зависимость от полного регистра. (Процессоры AMD не переименовывать субрегистры отдельно в первую очередь. Intel P4 и посадки Silvermont/Рыцарский являются таким же образом.)
Intel Хасуэлл/Skylake (и, возможно, Ivybridge) не переименовывать al
отдельно от rax
вообще, поэтому им никогда не нужно объединять регистры low8/low16. Но setcc al
имеет ложную зависимость от старого значения. Они все еще переименовывают и объединяют ah
. (Details on HSW/SKL partial-reg performance.)
# partial flag stall when reading a flag that didn't come from
# the last instruction to write any flags.
clc
# edi and esi = one-past-the-end of dst and src
# ecx = -count
bigInt_add:
mov eax, [esi+ecx*4]
adc [edi+ecx*4], eax # reads CF, partial flag stall on 2nd and later iterations
inc ecx # writes all flags except CF
jl bitInt_add # loop upwards towards zero
См this Q&A для более детального обсуждения вопросов о частичных флагов на Intel предварительной SandyBridge против SandyBridge.
Смотрите также Agner Fog's microarch pdf и другие ссылки в x86 тегов вики для получения более подробной информации обо всем этом.
Имеются штрафы за 16-разрядные обращения. Использование 32-разрядных регистров и исключение r8-r15 в порядке и фактически часто приводит к меньшему размеру кода. –
Запись в 32-битный регистр автоматически очищает верхние 32 бита, поэтому избегает проблемы частичного обновления. – Jester
Регистр EFLAGS сильно виртуализирован в современных процессорах. Как и все регистры. Обязательно так, слишком много инструкций модифицируют его, и это большой заслон над суперскалярным исполнением. В коде отсутствует код, который фактически использует * регистр. Таким образом, нет никакой веской причины, по которой процессор блокирует его и останавливает отправленный вами код. Никогда не задумывайтесь над тем, как это должно/работать. Единственная точка написания ассемблерного кода - сделать его быстрее, чем компилятор C. Мера. –