devirtualize:由于某些保证更改是正确的,将虚拟/多态/间接函数调用更改为静态函数调用 - 来源:我自己
给定一个&dyn ToString使用静态已知类型创建的简单特征对象String:
fn main() {
let name: &dyn ToString = &String::from("Steve");
println!("{}", name.to_string());
}
Run Code Online (Sandbox Code Playgroud)
请问直接调用.to_string()使用<String as ToString>::to_string()吗?还是仅通过 trait 的 vtable 间接?如果是间接的,是否可以将这个调用去虚拟化?或者有什么基本的东西阻碍了这种优化?
这个问题的激励代码要复杂得多;它使用异步特征函数,我想知道Box<dyn Future>在某些情况下是否可以优化返回 a 。
struct base {
virtual void vcall() = 0;
};
struct foo final : base {
void vcall() final;
};
void call_base(base& b) {
b.vcall();
}
void call_foo(foo& f) {
call_base(f);
}
void call_foo_directly(foo& f) {
f.vcall();
}
Run Code Online (Sandbox Code Playgroud)
clang 16 产生:
call_base(base&):
mov rax, qword ptr [rdi]
jmp qword ptr [rax]
call_foo(foo&):
mov rax, qword ptr [rdi]
jmp qword ptr [rax]
call_foo_directly(foo&):
jmp foo::vcall()@PLT
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 产生相同的结果,因此这不是仅限于 clang 的问题。是否也应该call_foo包含非虚拟调用foo::vcall()?这是错过的优化,还是调用有可能是虚拟的?
考虑以下代码:
struct A {
virtual A& operator+=(const A& other) noexcept = 0;
};
void foo_inner(int *p) noexcept { *p += *p; }
void foo_virtual_inner(A *p) noexcept { *p += *p; }
void foo(int *p) noexcept
{
return foo_inner(p);
}
struct Aint : public A {
int i;
A& operator+=(const A& other) noexcept override final
{
// No devirtualization of foo_virtual with:
i += dynamic_cast<const Aint&>(other).i;
// ... nor with:
// i += reinterpret_cast<const Aint&>(other).i;
return *this;
}
};
void foo_virtual(Aint …Run Code Online (Sandbox Code Playgroud) c++ gcc virtual-functions compiler-optimization devirtualization