【问题标题】:Static Branch prediction for the ARM with __builtin_expect is not functional!!?带有 __builtin_expect 的 ARM 的静态分支预测不起作用!!?
【发布时间】:2012-02-12 06:35:51
【问题描述】:

我正在对 Cortex-R4 中运行的 C 代码进行优化。 首先,当我在条件检查中指出“__builtin_expect”时,我没有看到汇编代码输出有任何变化。 似乎编译器生成了不必要的跳转。

我的 C 代码:

           bit ++; (Likely)

if(__builtin_expect(bit >= 32),0) 
{ 
  bit -=32; // unlikely code
  xxxxxx;   // unlikely code
  xxxxxx;   // unlikely code
  xxxxxx;   // unlikely code
} 

bit = bit*2 // something  (Likely)
return bit; 

---- 生成的 ASM 代码 -------- (位 => r0)

                      ADD   r2,r2,#1 
                      CMP   r0,#0x20 
                      BCC  NoDecrement 
                      SUB   r0,r0,#0x20 
                      XXXXXXXXX 
                      XXXXXXXXX 
                      XXXXXXXXX 
NoDecrement LSL   r0,r0,#1 
                          BX  lr 

---- 我预期的 ASM 代码 --------

                          ADD   r2,r2,#1 
                          CMP   r0,#0x20 
                          BHE   Decrement 
JumbBack       LSL   r0,r0,#1 
                          BX  lr 
Decrement      SUB   r0,r0,#0x20 
                          XXXXXXXXX 
                          XXXXXXXXX 
                          XXXXXXXXX 
                          B JumbBack

假设如果这段 C 代码在循环中运行,那么每次它都要跳转(因为 if 条件只通过了一次)。 是否有任何其他编译器设置实际上可以按预期生成代码..??

【问题讨论】:

    标签: performance arm optimization branch-prediction


    【解决方案1】:

    你写道:

    if(__builtin_expect(bit >= 32),0)
    {
        ...
    }
    

    花括号内的代码将永远被执行,因为它被if(foo,0)包围,对于foo的任何值,它都相当于if(0),无论你是什么内置的试图使用。如果您使用-O2 打开优化,您会看到编译器完全删除了死代码,而不是直接跳过它。我想你可能打算写

    if (__builtin_expect(bit >= 32, 0)) {
        bit -= 32;
    }
    

    如果我这样做,我会得到我期望的正向分支(clang -O1 或更高版本)。

    extern void something();
    int foo(int bit)
    {
        ++bit;
        if (__builtin_expect(bit >= 32, 0)) {
            bit -= 32;  // "Decrement"
            something();
        }
        bit = bit*2;
        something();
        return bit;
    }
    

    这是来自clang -arch armv7 -O2 -S的代码:

    _foo:
    @ BB#0:
    push    {r4, r7, lr}
    adds    r4, r0, #1
    add r7, sp, #4
    cmp r4, #32
    bge LBB0_2           // a forward branch for the unlikely case
    LBB0_1:
    lsls    r4, r4, #1
    blx _something
    mov r0, r4
    pop {r4, r7, pc}
    LBB0_2:                      // "Decrement"
    sub.w   r4, r0, #31
    blx _something
    b   LBB0_1
    

    【讨论】:

      猜你喜欢
      • 2014-02-21
      • 2013-09-04
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2015-10-17
      • 1970-01-01
      • 2020-04-04
      • 2014-04-25
      相关资源
      最近更新 更多