c ++ bitset没有内联?

时间:2013-12-13 01:42:52

标签: c++ g++ 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也没有帮助,它完全优化了代码。 无论如何我可以避免调用函数吗?

2 个答案:

答案 0 :(得分: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的建议,我也进行了第二次测试。这个通过从volatile初始化bitset并从argc返回计算值来消除main变量:

#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

请注意,当您不知道xorl的实际初始化值时,它确实优化了最小数量的计算步骤(orl后跟bitset)在编译时。第三条指令(movl %edi, %eax)只是将argc从它到达的寄存器移动到将返回结果的寄存器。

答案 1 :(得分:2)

如果您担心调用函数,为什么要使用bitset?

怎么样

unsigned int bit32; // Assume int is 32 bits

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