c++ bitset not inlined?

395 views Asked by At

I try out the below:

#include <bitset>

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

Using GCC 4.8.1, I couldn't get it to inline, objdump gave me more or less:

  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 doesn't help either, it sort of optimize away the code entirely. Is there anyway I can avoid calling functions?

2

There are 2 answers

3
Ed Heal On

Why use bitset if you are worried about calling functions?

How about

unsigned int bit32; // Assume int is 32 bits

bit32 = 0xf0f0f0f0;
bit32 ^= 16;
bit32 |= 1;
1
Joe Z On

Compile with optimizations enabled. When I compile with g++ -std=c++11 -O3 and the following slightly modified code, it outputs very optimized code:

Input:

#include <bitset>

volatile unsigned long v;

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

    v = bit32.to_ulong();
}

Compiler output:

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

I needed to add the volatile variable to keep G++ from optimizing it completely away. It basically optimized all of the bitset operations down to a single movl instruction.

Applying @GlennTeitelbaum's suggestion below, I also ran a second test. This one eliminates the volatile variable by initializing the bitset from argc, and returning the computed value from main:

#include <bitset>

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

    return bit32.to_ulong();
}

This one generated the following compiler output (same flags as above):

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

Notice that it did optimize down to the minimum number of computational steps (xorl followed by orl) that are necessary when you don't know the actual initializer value to the bitset at compile time. The third instruction (movl %edi, %eax) is there just to move argc from the register it arrives in to the register that the result will be returned in.