[clang] [llvm] [WPD] Support speculative devirtualization with LTO (PR #233380)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 20 05:54:37 PDT 2026
================
@@ -1131,12 +1120,6 @@ bool DevirtModule::tryFindVirtualCallTargets(
if (Fn->getName() == "__cxa_pure_virtual")
continue;
- // In most cases empty functions will be overridden by the
- // implementation of the derived class, so we can skip them.
- if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
----------------
KRM7 wrote:
There aren't speculative/non-speculative modes after the changes, both could be performed in the same module, and this function is shared by the speculative and single-impl cases, so it has to work for both. For example, consider something like this:
```ll
@vtable.empty = linkonce_odr hidden constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @empty] }, !type !0, !vcall_visibility !1
@vtable.nonempty = linkonce_odr hidden constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @nonempty] }, !type !0, !vcall_visibility !1
define void @empty(ptr %this) { ; ignored in tryFindVirtualCallTargets()
ret void
}
declare void @f()
define void @nonempty(ptr %this) {
call void @f()
ret void
}
define void @test(ptr %p) {
entry:
%vtable = load ptr, ptr %p
%ok = call i1 @llvm.type.test(ptr %vtable, metadata !"T")
call void @llvm.assume(i1 %ok)
%fn = load ptr, ptr %vtable
call void %fn(ptr %p) ; devirtualized to call @nonempty
ret void
}
declare i1 @llvm.type.test(ptr, metadata)
declare void @llvm.assume(i1)
!0 = !{i64 16, !"T"}
!1 = !{i64 1}
```
With the check and speculative devirtualization enabled, the `@empty` function would be ignored, and the indirect call in `@test` would be replaced with an unguarded direct call to `@nonempty`, which is wrong.
https://github.com/llvm/llvm-project/pull/233380
More information about the cfe-commits
mailing list