Ответ 1
Говорят, что условные переходы преобразуются в команды условного перемещения, cmove
команд. Они улучшают скорость, потому что они не останавливают процессорный конвейер, как скачки.
С инструкциями перехода вы не знаете, в каких продвинутых инструкциях для загрузки, поэтому используется предсказание, и ветка загружается в конвейер. Если предсказание было правильным, все хорошо, следующие инструкции уже выполняются на конвейере. Однако после того, как скачок был оценен, если предсказание было неправильным, все последующие инструкции, уже находящиеся в конвейере, бесполезны, поэтому конвейер должен быть освобожден и загружены правильные инструкции. Современные процессоры содержат 16-30 этапов трубы, а неверные предсказания отрасли сильно ухудшают производительность. Условные перемещения обходят это, потому что они не вставляют ветки в поток программы.
Но пишет ли cmove всегда?
Из справки по набору инструкций Intel x86:
Инструкции CMOVcc проверяют состояние одного или нескольких флажков состояния в регистре EFLAGS [..] и выполняют операцию перемещения, если флаги находятся в определенном состоянии (или состоянии). [..] Если условие не выполнено, движение не выполняется, и выполнение продолжается с инструкцией, следующей за инструкцией CMOVcc.
Edit
После дальнейшего изучения руководства gcc я запутался, поскольку, насколько я знаю, компилятор не оптимизирует преобразование кода C в другой код C, но использует внутренние структуры данных, такие как Control Flow Graphs, поэтому я действительно не знаю, что они имеют в виду их пример. Я предполагаю, что они означают эквивалент C нового генерируемого потока. Я уже не уверен, если эта оптимизация связана с генерацией cmoves
.
Изменить 2
Так как cmove
работает с регистрами, а не с памятью, это
if (cond)
A[i] = expr
не может генерировать cmove
.
Однако это
A[i] = cond ? expr : A[i];
может.
Предположим, что в bx
значение expr
.
load A[i] into ax
cmp // cond
cmove ax, bx
store ax into &A[i]
Итак, чтобы использовать cmove
, вы должны прочитать значение A [i] и записать его, если cond if false, что не эквивалентно оператору if, но с тернарным оператором.