Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual C++ : No devirtualization in obvious cases?

I was very surprised when watching the code generated by visual c++ (VS2017 RC) to see dynamic branching (virtual call) in simple cases.

So I tried the following code with the compiler explorer:

struct Base
{
  virtual void foo() = 0;
};

struct Impl : Base
{
void foo() override;
};

Impl g_impl;
void globalCall()
{
  g_impl.foo();
}

void localCall()
{
  Impl i;
  i.foo();
}

void tempCall()
{
  Impl().foo(); // dynamic branching generated!
}

struct Class
{
  void memberCall();
  Impl impl;
};

void Class::memberCall()
{
  impl.foo(); // dynamic branching generated!
} 

Compiler explorer link: https://godbolt.org/g/RmUku2

With the temporary and the member cases, it looks like no devirtualization occurs. So is it a compiler quality of implementation issue, or is there technical valid reasons for such result?

like image 460
RTempete Avatar asked Jan 31 '17 02:01

RTempete


1 Answers

Just missed cases for devirtualization. It has been like this since the first version in which devirtualization was supported, namely VS 2013. The other compilers gcc, icc, and clang perform devirtualization in all the cases. In general, it is better to explicitly specify final rather than relying on the compiler to pedantically perform devirtualization. Marking Impl.foo with final enables the optimization in all the cases.

like image 97
Hadi Brais Avatar answered Nov 15 '22 06:11

Hadi Brais