已知分支行为时如何控制编译器分支生成方式
已知数据分支行为模式时,如何引导编译器生成更优的分支或条件选择指令?
我已经熟悉编译器内置函数__builtin_expect以及Clang专属的__builtin_unpredictable,二者能解决部分分支优化问题,但仍存在覆盖不到的场景。
举个简单的示例代码:
void highly_contrived_example(unsigned int * numbers, unsigned int count) { unsigned int * const end = numbers + count; for (unsigned int * iterator = numbers; iterator != end; ++ iterator) foo(* iterator % 2 == 0 ? 420 : 69); }
这段代码逻辑很简单:遍历数组,遇到偶数就以420为参数调用foo(),奇数则传入69。
现在假设我们提前明确数据的分布模式:
- 若数据完全随机,使用条件选择指令(比如ARM的
csel、x86的cmov等)比分支跳转更高效; - 若数据呈现高度可预测的连续模式(比如连续一段偶数后接连续一段奇数),则分支跳转更合适。
但当奇偶数量相近时,__builtin_expect无法发挥作用;而__builtin_unpredictable仅支持Clang,我也不确定不用它是否会影响编译器生成条件选择指令。
我目前的“解决方案”是给编译器传递假信息:数据可预测时,用高概率的__builtin_expect引导生成分支;数据不可预测时,用__builtin_unpredictable引导生成条件选择指令,或者直接用内联汇编。但这显然不是最优解。
注:
- 0 我没做过实际基准测试,知道这个示例里分支未必比条件选择慢,仅作场景演示;
- 1 现代编译器通常能自主判断最优实现,我的问题针对的是编译器无法合理判断、且性能差异显著的小众场景。
我的核心问题是:已知数据的分支行为模式时,在__builtin_expect和__builtin_unpredictable无法满足需求的情况下,如何有效引导编译器生成更优的分支或条件选择指令?
内容的提问来源于stack exchange,提问作者Mona the Monad
相关产品推荐
相关产品推荐

