Я считаю, что наиболее распространенный способ избежать ветвления - использовать битовый параллелизм для уменьшения общего количества переходов, присутствующих в вашем коде. Чем длиннее основные блоки, тем реже промывается конвейер.
Как уже упоминал кто-то, если вы хотите сделать больше, чем просто развернуть циклы и предоставить подсказки ветвления, вы захотите перейти в сборку. Конечно, это должно быть сделано с предельной осторожностью: ваш типичный компилятор может написать лучшую сборку в большинстве случаев, чем человек. Ваша лучшая надежда - сбрить неровности и сделать предположения, которые компилятор не сможет вывести.
Вот пример следующего кода C:
if (b > a) b = a;
В сборке без скачков, с использованием битовых манипуляций (и экстремального комментирования):
sub eax, ebx ; = a - b
sbb edx, edx ; = (b > a) ? 0xFFFFFFFF : 0
and edx, eax ; = (b > a) ? a - b : 0
add ebx, edx ; b = (b > a) ? b + (a - b) : b + 0
Обратите внимание, что, хотя условные ходы сразу же запускаются энтузиастами сборки, это только потому, что они легко понятны и предоставляют концепцию языка более высокого уровня в удобной отдельной инструкции. Они не обязательно быстрее, недоступны на старых процессорах, и, сопоставляя код C с соответствующими инструкциями условного перемещения, вы просто выполняете работу компилятора.