2012-01-17 30 views
0

我正在Cortex-R4中運行的C代碼中進行優化。 首先,我在條件檢查中指出「__builtin_expect」時沒有看到彙編代碼輸出中的任何更改。 這似乎是編譯器生成不必要的跳轉。具有__builtin_expect的ARM的靜態分支預測功能不起作用!!?

我的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代碼在一個循環運行,那麼每個具有時間跳(因爲如果條件被傳遞 只有一次)。 是否有任何其他編譯器設置,實際上,如預期的那樣生成代碼。

回答

6

您寫道:

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