除非您可以使用条件移动,否则 Ïf 语句会生成条件跳转,但这更有可能是在手写汇编中完成的。有一些规则可以控制 CPU 的条件跳转假设(分支预测),因此按照规则运行的条件跳转的惩罚是可以接受的。然后是乱序执行使事情变得更加复杂:)。底线是,如果您的代码是直截了当的,那么最终发生的跳转不会影响性能。您可以查看 Agner Fog 的优化页面。
C 代码的非调试编译特别应该生成四个条件跳转。逻辑与 (&&) 和括号的使用将导致从左到右的测试,因此一个 C 优化可能是首先测试最有可能大于 0.0f 的 f32(如果可以确定这样的概率)。您有五种可能的执行变体:test1 true 采用分支 (t1tbt)、test1 false 无分支 (t1fnb) test2 true 分支采用 (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(长)。负浮点值与正浮点值具有完全相同的格式,除了设置了最高位 (0x80000000)。