LTO devirtualization not works on gcc-9.3

Xi Ruoyao xry111@mengyan1223.wang
Wed May 12 16:47:23 GMT 2021


On Wed, 2021-05-12 at 23:54 +0800, 陈云星 via Gcc-help wrote:
> 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);
> }

I think it's https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47316.
-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University



More information about the Gcc-help mailing list