|
|
|
|
|
by nwallin
792 days ago
|
|
You appear to be correct. Clang does not devirtualize in LTO, but GCC does. Personally I consider this very strange. $ cat animal.h cat.cpp main.cpp
// animal.h
#pragma once
class animal {
public:
virtual ~animal() {}
virtual void speak() = 0;
};
animal& get_mystery_animal();
// cat.cpp
#include "animal.h"
#include <cstdio>
class cat final : public animal {
public:
~cat() override{}
void speak() override{
puts("meow");
}
};
static cat garfield{};
animal& get_mystery_animal() {
return garfield;
}
// main.cpp
#include "animal.h"
int main() {
animal& a = get_mystery_animal();
a.speak();
}
$ make clean && CXX=clang++ make -j && objdump --disassemble=main -C lto_test
rm -f *.o lto_test
clang++ -c -flto -O3 -g cat.cpp -o cat.o
clang++ -c -flto -O3 -g main.cpp -o main.o
clang++ -flto -O3 -g cat.o main.o -o lto_test
lto_test: file format elf64-x86-64
Disassembly of section .init:
Disassembly of section .plt:
Disassembly of section .plt.got:
Disassembly of section .text:
00000000000011b0 <main>:
11b0: 50 push %rax
11b1: 48 8b 05 58 2e 00 00 mov 0x2e58(%rip),%rax # 4010 <garfield>
11b8: 48 8d 3d 51 2e 00 00 lea 0x2e51(%rip),%rdi # 4010 <garfield>
11bf: ff 50 10 call *0x10(%rax)
11c2: 31 c0 xor %eax,%eax
11c4: 59 pop %rcx
11c5: c3 ret
Disassembly of section .fini:
$ make clean && CXX=g++ make -j && objdump --disassemble=main -C lto_test|sed -e 's,^, ,'
rm -f *.o lto_test
g++ -c -flto -O3 -g cat.cpp -o cat.o
g++ -c -flto -O3 -g main.cpp -o main.o
g++ -flto -O3 -g cat.o main.o -o lto_test
lto_test: file format elf64-x86-64
Disassembly of section .init:
Disassembly of section .plt:
Disassembly of section .plt.got:
Disassembly of section .text:
0000000000001090 <main>:
1090: 48 83 ec 08 sub $0x8,%rsp
1094: 48 8d 3d 75 2f 00 00 lea 0x2f75(%rip),%rdi # 4010 <garfield>
109b: e8 50 01 00 00 call 11f0 <cat::speak()>
10a0: 31 c0 xor %eax,%eax
10a2: 48 83 c4 08 add $0x8,%rsp
10a6: c3 ret
Disassembly of section .fini:
|
|