LTO devirtualization not works on gcc-9.3

陈云星 chen.yunxing@me.com
Wed May 12 15:54:49 GMT 2021


In my test, class B inherent class A and B implements virtual function “get_c” of class A;

Because of there is only one sub-class of B ( which is A)

LTO compile was expected to devirtualize virtual function call “get_c”

However use gcc-9.3 to compile and link, the result was negative:

## build command
g++ -flto -c a.cc <http://a.cc/> -O2
g++ -flto -c b.cc <http://b.cc/> -O2
g++ -flto -c c.cc <http://c.cc/> -O2
g++ -flto -c m.cc <http://m.cc/> -O2
g++ -flto a.o b.o c.o m.o

## disassembly a.out
Objdump -d -C a.out 

0000000000400610 <A::s(char*)>:
  400610:	48 8b 07             	mov    (%rdi),%rax
  400613:	53                   	push   %rbx
  400614:	48 89 f3             	mov    %rsi,%rbx
  400617:	ff 10                	callq  *(%rax)
  400619:	48 85 db             	test   %rbx,%rbx
  40061c:	74 07                	je     400625 <A::s(char*)+0x15>
  40061e:	0f be 13             	movsbl (%rbx),%edx
  400621:	5b                   	pop    %rbx
  400622:	01 d0                	add    %edx,%eax
  400624:	c3                   	retq   
  400625:	83 c0 01             	add    $0x1,%eax
  400628:	5b                   	pop    %rbx
  400629:	c3                   	retq   
  40062a:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)

At "  400617:	ff 10                	callq  *(%rax)”
which call by virtual function dispatch


//  file a.h
#ifndef INCLUDE_A
#define INCLUDE_A
class A {
protected:
virtual int get_c() = 0;
public:
  int s(char* a);
};
#endif

// file a.cc <http://a.cc/>
#include "a.h"
int __attribute__((noinline)) A::s(char* a) {
     int c = get_c();
     if (a == 0) {
        return c + 1;
     }
     return c + a[0];
}

// file b.h
#include "a.h"
class B : public A {
public:
  B(int b, int c) : bbb(b), ccc(c) {}
  protected: 
   virtual int get_c() {
      return bbb == 0 ? ccc : ccc + bbb; 
   }
private:
  int bbb;
  int ccc;
};

// file b.cc <http://b.cc/>
#include “b.h"

// file c. <http://c.cc/>h
#include "a.h"
class C {
public:
	 C(A &a): a(a) {}
  int ss(char* b);
private:
  A &a;
};

// file c.cc <http://c.cc/>
#include "c.h"
int __attribute__ ((noinline)) C::ss(char* b) {
    return a.s(b);
}

// file m.cc <http://m.cc/>
#include "b.h"
#include "c.h"
int main(int argc, char** argv)
{
  B b(argc, argc+1);
  C c(b);
  return c.ss(*argv);
}


More information about the Gcc-help mailing list