C 将0映射到任何非零值的无分支方法,而不考虑其他值?

C 将0映射到任何非零值的无分支方法,而不考虑其他值?,c,performance,optimization,bit-manipulation,branch,C,Performance,Optimization,Bit Manipulation,Branch,我正试图找到此功能的最快实现方式: uint16_t forbid_zero(uint16_t x) { if(x == 0) return SOMETHING_NONZERO; return x; } 什么是非零并不重要,只要它不是零。除零以外的任何值都应不经修改地通过。做这件事最快的黑客是什么?我想有一些很好的无分支的方法 在上下文中,我在关键路径中有一个算法,其中零作为输入值将触发无限循环和其他不良行为,我很好奇是否有可能将输入设置为始终非零,而不进行分支

我正试图找到此功能的最快实现方式:

uint16_t forbid_zero(uint16_t x)
{
    if(x == 0)
        return SOMETHING_NONZERO;
    return x;
}

什么是非零并不重要,只要它不是零。除零以外的任何值都应不经修改地通过。做这件事最快的黑客是什么?我想有一些很好的无分支的方法


在上下文中,我在关键路径中有一个算法,其中零作为输入值将触发无限循环和其他不良行为,我很好奇是否有可能将输入设置为始终非零,而不进行分支以检查0。将不正确的非零值传递给算法的结果并不那么糟糕;错误将被其他层上已经存在的检查发现,因此将0映射到任何其他值就足够了。

一种可能的实现是:

uint16_t forbid_zero(uint16_t x)
{
    return x | !x;
}
编译资源管理器将显示:

但是,即使您在问题中使用同一编译器给出的实现:

forbid_zero(unsigned short):
        testw   %di, %di
        movl    $1, %eax
        cmovne  %edi, %eax
        ret

…当然也不能保证
!x也不会被编译成分支。

也许
return-!x | x“我认为有一种很好的无分支的方式。”好吧,你不能拿一段C代码来预测它最终将如何在处理器中执行(除非你在这方面非常有经验)。您需要编译代码并研究生成的二进制文件。即使在那里,由于处理器使用的所有技巧,也很难预测性能,因此最终可能不得不进行分析。在现代CPU上,完全可预测的分支几乎是免费的。避免分支主要与不可预测的分支有关。我很欣赏你们两位提出的观点,但没有必要在每个性能问题上都提出。如果有人知道请求无分支代码,可以安全地假设他们有理由。
forbid_zero(unsigned short):
        testw   %di, %di
        movl    $1, %eax
        cmovne  %edi, %eax
        ret