From 12d2363241aaa5f8ff4af3914122e24c38b1e1ce Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 6 Apr 2024 16:42:38 -0400 Subject: [PATCH] Increase vtable layout size This improves LLVM's codegen by allowing vtable loads to be hoisted out of loops (as just one example). --- compiler/rustc_middle/src/ty/layout.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 66078663098b1..85aa0088a1a79 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -771,11 +771,25 @@ where }); } - let mk_dyn_vtable = || { + let mk_dyn_vtable = |principal: Option>| { + let min_count = TyCtxt::COMMON_VTABLE_ENTRIES.len() + // As the comment below notes, it's hard to get access to supertraits + // here. Supertraits currently are determined by resolving predicates. + // It's not clear that it's easy to do that here. So, for now, we're + // just increasing the vtable size by the local, direct vtable entries. + // We know that *at least* that many pointers will be needed, + // which is already a win for some cases. As an example, this lets LLVM + // better hoist vtable loads out of loops for calls to `&mut dyn FnMut` + // function arguments. + + principal + .map(|principal| { + tcx.own_existential_vtable_entries(principal.def_id()).len() + }) + .unwrap_or(0); Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, - Ty::new_array(tcx, tcx.types.usize, 3), + Ty::new_array(tcx, tcx.types.usize, min_count.try_into().unwrap()), ) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the @@ -808,16 +822,16 @@ where // `std::mem::uninitialized::<&dyn Trait>()`, for example. if let ty::Adt(def, args) = metadata.kind() && Some(def.did()) == tcx.lang_items().dyn_metadata() - && args.type_at(0).is_trait() + && let ty::Dynamic(data, _, ty::Dyn) = args.type_at(0).kind() { - mk_dyn_vtable() + mk_dyn_vtable(data.principal()) } else { metadata } } else { match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, - ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(), + ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), } };