2013-12-13 43 views
2

我嘗試以下:C++ bitset不內聯?

#include <bitset> 

int main() 
{ 
    std::bitset<32> bit32 { 0xf0f0f0f0 }; 
    bit32[4].flip(); 
    bit32[0] = 1; 
} 

使用GCC 4.8.1,我無法得到它內聯,objdump的給我或多或少:

401536: c7 45 e4 f0 f0 f0 f0 movl $0xf0f0f0f0,-0x1c(%ebp) 
    40153d: 8d 45 e8    lea -0x18(%ebp),%eax 
    401540: c7 44 24 04 04 00 00 movl $0x4,0x4(%esp) 
    401547: 00 
    401548: 8d 55 e4    lea -0x1c(%ebp),%edx 
    40154b: 89 14 24    mov %edx,(%esp) 
    40154e: 89 c1     mov %eax,%ecx 
    401550: e8 93 13 00 00   call 4028e8 <__ZNSt6bitsetILj32EEixEj> 
    401555: 83 ec 08    sub $0x8,%esp 
    401558: 8d 45 e8    lea -0x18(%ebp),%eax 
    40155b: 89 c1     mov %eax,%ecx 
    40155d: e8 b2 12 00 00   call 402814 <__ZNSt6bitsetILj32EE9reference4flipEv> 
    401562: 8d 45 e8    lea -0x18(%ebp),%eax 
    401565: 89 c1     mov %eax,%ecx 
    401567: e8 10 13 00 00   call 40287c <__ZNSt6bitsetILj32EE9referenceD1Ev> 
    40156c: 8d 45 f0    lea -0x10(%ebp),%eax 
    40156f: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp) 
    401576: 00 
    401577: 8d 55 e4    lea -0x1c(%ebp),%edx 
    40157a: 89 14 24    mov %edx,(%esp) 
    40157d: 89 c1     mov %eax,%ecx 
    40157f: e8 64 13 00 00   call 4028e8 <__ZNSt6bitsetILj32EEixEj> 
    401584: 83 ec 08    sub $0x8,%esp 
    401587: 8d 45 f0    lea -0x10(%ebp),%eax 
    40158a: c7 04 24 01 00 00 00 movl $0x1,(%esp) 
    401591: 89 c1     mov %eax,%ecx 
    401593: e8 f0 12 00 00   call 402888 <__ZNSt6bitsetILj32EE9referenceaSEb> 
    401598: 83 ec 04    sub $0x4,%esp 
    40159b: 8d 45 f0    lea -0x10(%ebp),%eax 
    40159e: 89 c1     mov %eax,%ecx 
    4015a0: e8 d7 12 00 00   call 40287c <__ZNSt6bitsetILj32EE9referenceD1Ev> 
    4015a5: b8 00 00 00 00   mov $0x0,%eax 
    4015aa: 8b 4d fc    mov -0x4(%ebp),%ecx 

-O1,-O2, -O3也沒有幫助,它完全優化代碼。 反正我可以避免調用函數嗎?

+3

爲什麼調用函數會導致問題? –

+0

@EdHeal:我確定它比它應該優化的速度慢得多(例如,一個'movl'指令,就像它爲我所做的那樣)。對於這個微小的測試用例來說這可能不是什麼大問題,但是如果它在某個地方的循環中處於性能危急的代碼中,那將會產生所有差異。 –

+2

所以,你的問題是,代碼是未優化的,除非你告訴編譯器優化,在這種情況下,它優化它? – Casey

回答

2

如果您擔心調用函數,爲什麼要使用bitset?

如何

unsigned int bit32; // Assume int is 32 bits 

bit32 = 0xf0f0f0f0; 
bit32 ^= 16; 
bit32 |= 1; 
+0

@GlennTeitelbaum - XOR翻轉比特 –

+0

糟糕 - 錯過了4位 –

+0

好了+1現在爲更高效的解決方案 –

5

編譯優化啓用。當我與g++ -std=c++11 -O3和下面的略微修改後的代碼進行編譯,它輸出非常優化的代碼:

輸入:

#include <bitset> 

volatile unsigned long v; 

int main() 
{ 
    std::bitset<32> bit32 { 0xf0f0f0f0 }; 
    bit32[4].flip(); 
    bit32[0] = 1; 

    v = bit32.to_ulong(); 
} 

編譯器輸出:

main: 
.LFB958: 
    .cfi_startproc 
    movl $4042322145, %eax 
    movq %rax, v(%rip) 
    xorl %eax, %eax 
    ret 
    .cfi_endproc 

我需要添加的volatile變量,以保持G ++完全將其優化。它基本上優化了所有的bitset操作,直到單個movl指令。

下面應用@ GlennTeitelbaum的建議,我也跑了第二個測試。這一個從argc初始化bitset,並返回從main計算值消除了volatile變量:

#include <bitset> 

int main (int argc, char *argv[]) 
{ 
    std::bitset<32> bit32 = argc; 
    bit32[4].flip(); 
    bit32[0] = 1; 

    return bit32.to_ulong(); 
} 

這一個生成以下編譯器的輸出(如上述相同的標誌):

main: 
.LFB958: 
    .cfi_startproc 
    movl %edi, %eax 
    xorl $16, %eax 
    orq $1, %rax 
    ret 

通知當編譯時你不知道bitset的實際初始化值時,它確實需要優化到最小計算步數(xorl後跟orl)。第三條指令(movl %edi, %eax)只是爲了將argc從寄存器中移到寄存器中而返回結果。

+0

嘗試用argc初始化bitset,然後返回v –