Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make use of short and definition-available virtual methods for optimization?

I am just wondering if most compilers can do the following optimization

class A
{
    virtual void f() { m = 5; }
    void g() { f(); }
    int m;
};

f() is a virtual function and thus is not inline. However, can the compiler optimize g() for calling f() as inline since the definition of f() is short and available?

like image 716
user1899020 Avatar asked Mar 20 '23 22:03

user1899020


2 Answers

can the compiler optimize g() for calling f() as inline since the definition of f() is short and available?

That's pretty convoluted. g() can be inlined, such that calling A::g() generates the same optimised code as calling A::f(). If you derive from A, g() can still be inlined regardless of whether it's called on a variable for which runtime type is known at compile time or via an A* or A& to an object of unknown runtime type.

But, that's got nothing to do with f() being "short and available" - so I'm guessing your intent is to ask whether f() itself can be inlined: sometimes, specifically - when the runtime type is known at compile time f() itself may be inlined too.

struct B : A { void f() { ... } }
B b;
b.g();  // g() and B::f() may be inlined
A* p = &b;
p->g(); // g() and B::f() may be inlined (latter iff optimiser tracks p addressing a B)
p = opaque_factory();  // definition not known to compiler
p->g(); // equivalent to p->f();, g() inline, f() dispatched virtually / not inline.

void x(A* p) { p->g(); }  // g() may be inlined
x(p); // iff x is inlined, g() and B::f() may be too - per p->g() call above
      // iff x is out-of-line, and compiler doesn't do full-program analysis and find
      //    it's only ever called for a specific runtime type (unlikely if not a
      //    single-translation-unit program), then dispatch to f() can not be inlined
      //    and must be virtual

By not just declaring but actually defining g() (i.e. providing implementation) in the class definition, you implicitly tell the compiler g() can be inline.

The lack of overhead of g() is one reason the Non Virtual Interface idiom (where the virtual functions are made non-public and accessed via non-virtual public functions, allowing easy later customisation of the base class wrapper function to add instrumentation/logging etc. if needed) is attractive - there's no performance cost in optimised builds while extra functionality's not (yet) been added.

like image 93
Tony Delroy Avatar answered Mar 22 '23 13:03

Tony Delroy


I don't think they can. Here's why:

class B : public A
{
   virtual void f() {}
}

B b;
b.g(); // This must result in B::f() getting called.
like image 20
R Sahu Avatar answered Mar 22 '23 11:03

R Sahu