Компиляторы часто предпочитают if-преобразование в cmov, когда обе стороны ветви короткие, особенно с троичным, поэтому вы всегда назначаете переменную C. Например, if(x) y=bar;
иногда не оптимизируется под CMOV, но y = x ? bar : y;
чаще использует CMOV. Особенно, когда y
является записью массива, которая в противном случае не была бы затронута: введение неатоми c RMW могло бы создать гонку данных, отсутствующую в источнике. (Компиляторы не могут придумывать записи для объектов с общим доступом.)
Очевидный пример того, когда преобразование if было бы законным, но явно не выгодным, было бы, когда по обе стороны от if / было выполнено много работы. остальное. например, некоторые умножают и делят, целые l oop и / или таблицы поиска. Даже если g cc может доказать, что безопасно запускать обе стороны и выбирать один результат в конце, он увидит, что выполнение этой гораздо большей работы не стоит избегать ветвления.
If-преобразование в зависимость от данных (без ветвления cmov) возможна только в ограниченных случаях. Например, Почему g cc разрешено спекулятивно загружать из структуры? показывает случай, когда это можно / нельзя сделать. Другие случаи включают в себя доступ к памяти, которого нет у абстрактной машины C, что компилятор не может доказать, что это не будет ошибкой. Или не встроенный вызов функции, который может иметь побочные эффекты.
См. Также эти вопросы о получении g cc для использования CMOV.
См. Также Отключение предикации в gcc / g ++ - очевидно, gcc -fno-if-conversion -fno-if-conversion2
отключит использование cmov.
Для случая, когда cmov ухудшает производительность, см. g cc флаг оптимизации -O3 делает код медленнее, чем -O2 - G CC -O3
нуждается в оптимизации на основе профиля, чтобы получить правильную и использовать ветвь для if
, который оказывается весьма предсказуемым. G CC -O2
не выполнял преобразование if, даже без данных профилирования P GO.
Другой пример: Есть ли веская причина, по которой G CC будет генерировать прыжок, чтобы перепрыгнуть только через одну дешевую инструкцию?
G CC s изрядно пропускает простую оптимизацию показывает случай, когда троичный имеет побочные эффекты в обеих половинах: троичный не похож на CMOV: только одна сторона даже оценивается для побочных эффектов.
AVX-512 и Ветвление показывает пример на Фортране, где G CC нужна помощь от изменений источника, чтобы иметь возможность использовать SIMD без ответвлений. (Эквивалент скалярного CMOV). Это случай не изобретать записи: он не может превратить чтение / ветвь в чтение / возможно-изменение / запись для элементов, которые источник не написал бы. Если для векторизации обычно требуется преобразование if.