0

我在 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 代码 -------- (bit => 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 条件只通过了一次)。是否有任何其他编译器设置实际上可以按预期生成代码..??

4

1 回答 1

7

你写了:

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

花括号内的代码永远不会被执行,因为无论你尝试使用什么内置函数,它都被它包围,if(foo,0)相当于if(0)任何值。foo如果你用 开启优化-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
于 2012-08-31T21:25:24.313 回答