在 C++ 中,分支预测器是否预测隐式条件语句?

M. *_*ves 1 c++ syntax conditional-statements branch-prediction

在这段代码中,它被写成result += runs[i] > runs[i-1];一个隐式条件语句。在 C++ 中,分支预测器是否对该语句进行预测?或者我是否必须明确使用if关键字来进行分支预测?

using namespace std; 
int progressDays(vector<int> runs) {
    if (runs.size() < 2) {return 0;}
    int result = 0;
    for (int i = 1; i < runs.size(); i++) {result += runs[i] > runs[i-1];}
    return result;
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*des 6

CPU 不直接运行 C++,它们运行机器代码。所以答案取决于你的 C++ 如何编译为汇编/机器代码。 您在 C++ 中表达程序逻辑的选择只会间接影响这一点。现代编译器可以并且将会将 C++if()语句if 转换为没有分支的 asm(也称为无分支)。(对于 GCC, at-O3比 at做得更积极-O2- 请参阅gcc 优化标志 -O3 使代码比 -O2 慢

在大多数架构中,有一些有效的方法可以相当直接地将比较结果转换为 0 或 1 整数。(或者branchlessly递增以不同的方式,或甚至更直接,例如AArch64的csinc/ csel/cinc指令,它确实有条件增量,读一个输入寄存器和标志)。 所以一般x < y用作整数值将无分支编译。

int conditional_inc(int x, int y, int z) {
    z += (x<y);
    return z;
}
Run Code Online (Sandbox Code Playgroud)

例如,在 Godbolt 编译器资源管理器上

# x86-64 clang -O3
conditional_inc(int, int, int)
        xor     eax, eax        # prepare a zeroed register for setl of the low byte, to extend to 32-bit.  (x86 is annoyingly clunky and inefficient at this)
        cmp     edi, esi
        setl    al              # EAX = AL = (x<y) signed compare
        add     eax, edx        # EAX += z in the retval register
        ret
Run Code Online (Sandbox Code Playgroud)

AArch64 效率更高,使用组合增量和选择指令替换 xor-zero/setcc/add。

conditional_inc(int, int, int):
        cmp     w0, w1           // compare
        cinc    w0, w2, lt       // use the flags result, and the other 2 inputs.
        ret
Run Code Online (Sandbox Code Playgroud)

所有这些,比如 x86-64 setcc,都只是 ALU 指令,而不是控制(程序计数器没有条件变化),所以有数据依赖而不是控制依赖,因此不需要分支预测,因为没有分支。(最著名的此类指令可能是 x86 cmovcc,但在这种情况下只setcc需要)


通常,比较与分支是分开的。您可以进行比较,然后在没有分支的情况下获得一个布尔值。(分支确实需要一些分支,但这可以是对整数或布尔值的零的隐式比较。)

所以这不是条件语句,它只是一个用作整数的布尔值。