tower120
tower120

Reputation: 5255

GCC and devirtualization inlining

Why, in the following code, compiler, knowing exact type, can't inline virtual function?

https://goo.gl/AgvefX

using namespace std;

struct Base{
    void fire(){
        show();
    }

    virtual void show() =0;/*{
        cout << "base";
    }*/
};

struct A : Base{
    inline __attribute__((__always_inline__)) void show() {
        cout << "a";
    }
};

int main() {
    A a;
  for (int i=0;i<1000;i++){
    a.fire();
  }
    //a.fire();

    return 0;
}

Can I do something about this, without CRTP?

Upvotes: 0

Views: 248

Answers (1)

Jens
Jens

Reputation: 9406

I'm not good at reading assembler code, but the way I see your example, when in main:

  1. 1000 is loaded into a register
  2. 1 is substracted,
  3. the address of "a" is loaded and
  4. the output operator is called before the
  5. jump back to the beginning of the loop.

I don't see a call to fire or show. It keeps the implementation for show, but it is not used. That is correct because it has external linkage.

If you put everything in an anonymous namespace, the implementation can be omitted.

Could you put your reasoning with the assembler code in your question? For reference, here is the generated assembler code from the provides link:

.LC0:
    .string "a"
A::show():
    movl    $1, %edx
    movl    $.LC0, %esi
    movl    std::cout, %edi
    jmp std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
main:
    pushq   %rbx
    movl    $1000, %ebx
.L3:
    movl    $1, %edx
    movl    $.LC0, %esi
    movl    std::cout, %edi
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    subl    $1, %ebx
    jne .L3
    xorl    %eax, %eax
    popq    %rbx
    ret
    subq    $8, %rsp
    movl    std::__ioinit, %edi
    call    std::ios_base::Init::Init()
    movl    $__dso_handle, %edx
    movl    std::__ioinit, %esi
    movl    std::ios_base::Init::~Init(), %edi
    addq    $8, %rsp
    jmp __cxa_atexit

Upvotes: 4

Related Questions