Я смущен, где использовать инструкции cmov
и где использовать инструкции jump
в сборке?
С точки зрения производительности:
- В чем разница между ними?
- Какой из них лучше?
Если возможно, объясните их разницу с примером.
Я смущен, где использовать инструкции cmov
и где использовать инструкции jump
в сборке?
С точки зрения производительности:
Если возможно, объясните их разницу с примером.
movcc - это так называемая предикатная инструкция. Эта фантазия говорит о том, что "эта инструкция выполняется при условии (предикат)".
Многие процессоры, включая x86, после выполнения арифметической операции (особенно сравнения инструкций), устанавливают биты кода условия, чтобы указать статус результата операции.
Команда условного перехода проверяет биты кода состояния для состояния и, если true, переходит к назначенной цели.
Поскольку скачок является условным, и процессор, как правило, имеет глубокий конвейер, биты кода состояния могут быть буквально не готовы для команды jmp для обработки, когда ЦП встречает команду jmp. Разработчики чипов могли просто подождать, пока трубопровод будет стекать (часто много тактов), а затем выполнить jmp, но это сделает процессор медленным.
Вместо этого большинство из них предпочитают иметь алгоритм предсказания ветвления, который предсказывает, каким путем будет проходить условный переход. Затем процессор может извлекать, декодировать и выполнять предсказанную ветку (или нет) и продолжать быстрое выполнение, при условии, что если биты кода состояния, которые, наконец, прибывают, оказываются неправильными для условного (ветвь неверного прогноза), процессор отменяет все они работают после ветки и повторно запускают программу, идущую по другому пути.
Условные переходы сложнее для конвейерного выполнения, чем обычные зависимости данных, потому что они могут изменить, какая команда должна быть следующей в потоке инструкций, проходящих через конвейер. Это называется зависимость управления, в отличие от зависимости данных (например, add
, где оба входа являются выходами других последних инструкций).
Прогнозы ветки оказываются очень хорошими, потому что большинство отраслей, как правило, имеют предвзятость относительно своего направления. (Филиал в конце большинства циклов, как правило, относится к верху, как правило). Поэтому большую часть времени процессор не должен отказываться от ошибочно предсказанной работы.
Если направление ветки очень непредсказуемо, тогда процессор будет считать неправильным около 50% времени, поэтому придется отменить работу. Это дорого.
ОК, теперь часто находит такой код:
cmp ...
jcc $
mov register1, register2
$: ; continue here
...
; use register1
Если предсказатель ветвления догадывается правильно, этот код выполняется быстро, независимо от того, в каком направлении идет ветка. Если он догадывается не так много... ох.
Таким образом, инструкция условного перемещения. Это шаг, который условно перемещает данные, основываясь на битах кода условия. Мы можем переписать выше:
cmp ...
movcc register1, register2
$: ; continue here
...
; use register1
Теперь у нас нет инструкций о разветвлении, и, следовательно, никаких неверных прогнозов, которые заставляют процессор отменять всю работу. Поскольку нет никакой зависимости от управления, следующие команды должны быть извлечены и декодированы независимо от того, действует ли movcc
как mov
или nop
. Конвейер может оставаться полным, не предсказывая условия и спекулятивно выполняя инструкции, которые используют register1
. (Вы могли бы построить CPU таким образом, но это превзошло бы цель movcc
.)
movcc
преобразует зависимость управления в зависимость данных. Процессор обрабатывает его точно так же, как математическая инструкция с 3 входами, причем входы являются EFLAGS и двумя "обычными" входами (регистр dest и регистр источника или память). На x86, adc
идентичен cmovae
(mov if CF==0
), насколько способ выполнения вне очереди отслеживает зависимости: входы CF и оба регистра GP. Выходом является регистр назначения.
Для x86 существуют cmovcc
, jcc
и setcc
инструкции для каждой комбинации условий cc. (setcc
задает адресату 0 или 1. В соответствии с этим условием он имеет зависимость данных от флагов и других входных зависимостей.)