Ïf-операторы генерируют условные переходы, если вы не можете использовать условные переходы, но, скорее всего, это будет сделано в рукописной сборке.Существуют правила, которые управляют предположениями условного перехода ЦП (прогнозирование ветвления), так что штраф за условный переход, который ведет себя по правилам, является приемлемым.Тогда есть неупорядоченное выполнение, чтобы дополнительно усложнить вещи :).Суть в том, что если ваш код прост, скачки, которые в конечном итоге происходят, не повлияют на производительность.Вы можете проверить страницы оптимизации Agner Fog .
Неотладочная компиляция вашего C-кода, в частности, должна генерировать четыре условных перехода.Использование логических ands (&&) и круглых скобок приведет к тестированию слева направо, поэтому одной из оптимизаций C может быть проверка f32, который, скорее всего, сначала будет> 0.0f (если такая вероятность может быть определена).У вас есть пять возможных вариантов выполнения: test1 истинная ветвь взята (t1tbt), test1 ложная без ветвления (t1fnb) test2 истинная ветвь взята (t2tbt) и т. Д., Предоставляя следующие возможные последовательности
t1tbt ; var.m128_f32[0] <= 0.0f
t1fnb t2tbt ; var.m128_f32[0] > 0.0f, var.m128_f32[1] <= 0.0f
t1fnb t2fnb t3tbt ; var.m128_f32[0] > 0.0f, var.m128_f32[1] > 0.0f,
; var.m128_f32[2] <= 0.0f
t1fnb t2fnb t3fnb t4tbt ; var.m128_f32[0] > 0.0f, var.m128_f32[1] > 0.0f,
; var.m128_f32[2] > 0.0f, var.m128_f32[3] <= 0.0f
t1fnb t2fnb t3fnb t4fnb ; var.m128_f32[0] > 0.0f, var.m128_f32[1] > 0.0f
; var.m128_f32[2] > 0.0f, var.m128_f32[3] > 0.0f
Только взятая ветвь будетприведет к сбою конвейерной обработки, а предсказание ветвлений сведет к минимуму разрушение в максимально возможной степени.
Предполагая, что поплавки дороги в тестировании (если они есть), если var - объединение, и вы хорошо разбираетесь в элементах с плавающей точкойи выходы вы могли бы рассмотреть возможность целочисленного тестирования на перекрывающихся типах.Например, сохраненное значение 1.0f занимает четыре байта, сохраненные как 0x00, 0x00, 0x80, 0x3f (x86 / little-endian).Чтение этого значения как длинного целого даст 0x3f800000 или +1065353216.0.0f - это 0x00, 0x00, 0x00, 0x00 или 0x00000000 (long).Отрицательные значения с плавающей запятой имеют тот же формат, что и положительные, за исключением того, что установлен старший бит (0x80000000).