struct Foo {
Foo() {}
virtual ~Foo() {}
virtual void f() {}
int x;
};
int main() {
Foo *p = new Foo();
p->f();
delete p;
}
When RTTI data is disabled (/GR- / -fno-rtti-data), we cannot devirtualize the call to Foo::f. We can optimize the vptr load, but the vtable alias inhibits full devirtualization. See this instruction:
call qword ptr [rip + "??_7Foo@@6B@"+8]
LLVM knows exactly which vtable we are loading from, but because of the MSVC RTTI alias code pattern, it refuses to optimize away the load.
We should either make the optimize more aggressive, or find a better IR pattern for MSVC-style RTTI.
Extended Description
Consider this simple case when devirtualization should be possible after inlining the constructor: https://gcc.godbolt.org/z/osGe67s9b
struct Foo { Foo() {} virtual ~Foo() {} virtual void f() {} int x; }; int main() { Foo *p = new Foo(); p->f(); delete p; }
When RTTI data is disabled (/GR- / -fno-rtti-data), we cannot devirtualize the call to Foo::f. We can optimize the vptr load, but the vtable alias inhibits full devirtualization. See this instruction: call qword ptr [rip + "??_7Foo@@6B@"+8]
LLVM knows exactly which vtable we are loading from, but because of the MSVC RTTI alias code pattern, it refuses to optimize away the load.
We should either make the optimize more aggressive, or find a better IR pattern for MSVC-style RTTI.
Arthur had a patch to address this, but maybe it isn't sound: https://reviews.llvm.org/D99240