virtual-function-elimination

This option controls whether LLVM runs the Virtual Function Elimination (VFE) optimization. This optimization in only available with LTO, so this flag can only be passed if -Clto is also passed.

VFE makes it possible to remove functions from vtables that are never dynamically called by the rest of the code. Without this flag, LLVM makes the really conservative assumption, that if any function in a vtable is called, no function that is referenced by this vtable can be removed. With this flag additional information are given to LLVM, so that it can determine which functions are actually called and remove the unused functions.

Limitations

At the time of writing this flag may remove vtable functions too eagerly. One such example is in this code:

#![allow(unused)]
fn main() {
trait Foo { fn foo(&self) { println!("foo") } }

impl Foo for usize {}

pub struct FooBox(Box<dyn Foo>);

pub fn make_foo() -> FooBox { FooBox(Box::new(0)) }

#[inline]
pub fn f(a: FooBox) { a.0.foo() }
}

In the above code the Foo trait is private, so an assumption is made that its functions can only be seen/called from the current crate and can therefore get optimized out, if unused. However, with make_foo you can produce a wrapped dyn Foo type outside of the current crate, which can then be used in f. Due to inlining of f, Foo::foo can then be called from a foreign crate. This can lead to miscompilations.