mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Auto merge of #75155 - davidtwco:polymorphization-incr-comp-optimisations, r=lcnr
polymorphization: various improvements This PR includes a handful of polymorphisation-related changes: - @Mark-Simulacrum's suggestions [from this comment](https://github.com/rust-lang/rust/pull/74633#issuecomment-668684433): - Use a `FiniteBitSet<u32>` over a `FiniteBitSet<u64>` as most functions won't have 64 generic parameters. - Don't encode polymorphisation results in metadata when every parameter is used (in this case, just invoking polymorphisation will probably be quicker). - @lcnr's suggestion [from this comment](https://github.com/rust-lang/rust/pull/74717#discussion_r463690015). - Add an debug assertion in `ensure_monomorphic_enough` to make sure that polymorphisation did what we expect. r? @lcnr
This commit is contained in:
commit
7f8ff84b51
@ -1034,6 +1034,30 @@ pub trait FiniteBitSetTy:
|
||||
fn checked_shr(self, rhs: u32) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl FiniteBitSetTy for u32 {
|
||||
const DOMAIN_SIZE: u32 = 32;
|
||||
|
||||
const FILLED: Self = Self::MAX;
|
||||
const EMPTY: Self = Self::MIN;
|
||||
|
||||
const ONE: Self = 1u32;
|
||||
const ZERO: Self = 0u32;
|
||||
|
||||
fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
self.checked_shl(rhs)
|
||||
}
|
||||
|
||||
fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
self.checked_shr(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for FiniteBitSet<u32> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:032b}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FiniteBitSetTy for u64 {
|
||||
const DOMAIN_SIZE: u32 = 64;
|
||||
|
||||
|
@ -1150,7 +1150,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
.decode((self, tcx))
|
||||
}
|
||||
|
||||
fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u64> {
|
||||
fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u32> {
|
||||
self.root
|
||||
.tables
|
||||
.unused_generic_params
|
||||
|
@ -1134,8 +1134,11 @@ impl EncodeContext<'a, 'tcx> {
|
||||
debug!("EntryBuilder::encode_mir({:?})", def_id);
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
|
||||
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <-
|
||||
self.tcx.unused_generic_params(def_id));
|
||||
|
||||
let unused = self.tcx.unused_generic_params(def_id);
|
||||
if !unused.is_empty() {
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ define_tables! {
|
||||
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
|
||||
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
|
||||
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
|
||||
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u64>>>,
|
||||
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
|
@ -1319,7 +1319,7 @@ rustc_queries! {
|
||||
query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
|
||||
desc { "codegen_unit" }
|
||||
}
|
||||
query unused_generic_params(key: DefId) -> FiniteBitSet<u64> {
|
||||
query unused_generic_params(key: DefId) -> FiniteBitSet<u32> {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
desc {
|
||||
|tcx| "determining which generic parameters are unused by `{}`",
|
||||
|
@ -47,14 +47,26 @@ where
|
||||
unused_params.contains(index).map(|unused| !unused).unwrap_or(true);
|
||||
// Only recurse when generic parameters in fns, closures and generators
|
||||
// are used and require substitution.
|
||||
if is_used && subst.needs_subst() {
|
||||
match (is_used, subst.needs_subst()) {
|
||||
// Just in case there are closures or generators within this subst,
|
||||
// recurse.
|
||||
if subst.super_visit_with(self) {
|
||||
(true, true) if subst.super_visit_with(self) => {
|
||||
// Only return when we find a parameter so the remaining substs
|
||||
// are not skipped.
|
||||
return true;
|
||||
}
|
||||
// Confirm that polymorphization replaced the parameter with
|
||||
// `ty::Param`/`ty::ConstKind::Param`.
|
||||
(false, true) if cfg!(debug_assertions) => match subst.unpack() {
|
||||
ty::subst::GenericArgKind::Type(ty) => {
|
||||
assert!(matches!(ty.kind, ty::Param(_)))
|
||||
}
|
||||
ty::subst::GenericArgKind::Const(ct) => {
|
||||
assert!(matches!(ct.val, ty::ConstKind::Param(_)))
|
||||
}
|
||||
ty::subst::GenericArgKind::Lifetime(..) => (),
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
false
|
||||
|
@ -28,7 +28,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
/// Determine which generic parameters are used by the function/method/closure represented by
|
||||
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
|
||||
/// indicates all parameters are used).
|
||||
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u64> {
|
||||
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
debug!("unused_generic_params({:?})", def_id);
|
||||
|
||||
if !tcx.sess.opts.debugging_opts.polymorphize {
|
||||
@ -36,6 +36,13 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u64> {
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
|
||||
// Polymorphization results are stored in cross-crate metadata only when there are unused
|
||||
// parameters, so assume that non-local items must have only used parameters (else this query
|
||||
// would not be invoked, and the cross-crate metadata used instead).
|
||||
if !def_id.is_local() {
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
debug!("unused_generic_params: generics={:?}", generics);
|
||||
|
||||
@ -53,7 +60,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u64> {
|
||||
// Create a bitset with N rightmost ones for each parameter.
|
||||
let generics_count: u32 =
|
||||
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
|
||||
let mut unused_parameters = FiniteBitSet::<u64>::new_empty();
|
||||
let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
|
||||
unused_parameters.set_range(0..generics_count);
|
||||
debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
|
||||
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
|
||||
@ -84,7 +91,7 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
generics: &'tcx ty::Generics,
|
||||
unused_parameters: &mut FiniteBitSet<u64>,
|
||||
unused_parameters: &mut FiniteBitSet<u32>,
|
||||
) {
|
||||
if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
|
||||
for param in &generics.params {
|
||||
@ -110,11 +117,11 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||
fn mark_used_by_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
unused_parameters: &mut FiniteBitSet<u64>,
|
||||
unused_parameters: &mut FiniteBitSet<u32>,
|
||||
) {
|
||||
let def_id = tcx.closure_base_def_id(def_id);
|
||||
|
||||
let is_self_ty_used = |unused_parameters: &mut FiniteBitSet<u64>, self_ty: Ty<'tcx>| {
|
||||
let is_self_ty_used = |unused_parameters: &mut FiniteBitSet<u32>, self_ty: Ty<'tcx>| {
|
||||
debug!("unused_generic_params: self_ty={:?}", self_ty);
|
||||
if let ty::Param(param) = self_ty.kind {
|
||||
!unused_parameters.contains(param.index).unwrap_or(false)
|
||||
@ -123,7 +130,7 @@ fn mark_used_by_predicates<'tcx>(
|
||||
}
|
||||
};
|
||||
|
||||
let mark_ty = |unused_parameters: &mut FiniteBitSet<u64>, ty: Ty<'tcx>| {
|
||||
let mark_ty = |unused_parameters: &mut FiniteBitSet<u32>, ty: Ty<'tcx>| {
|
||||
let mut vis = UsedGenericParametersVisitor { tcx, def_id, unused_parameters };
|
||||
ty.visit_with(&mut vis);
|
||||
};
|
||||
@ -159,7 +166,7 @@ fn emit_unused_generic_params_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
generics: &'tcx ty::Generics,
|
||||
unused_parameters: &FiniteBitSet<u64>,
|
||||
unused_parameters: &FiniteBitSet<u32>,
|
||||
) {
|
||||
debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
|
||||
let base_def_id = tcx.closure_base_def_id(def_id);
|
||||
@ -195,7 +202,7 @@ fn emit_unused_generic_params_error<'tcx>(
|
||||
struct UsedGenericParametersVisitor<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
unused_parameters: &'a mut FiniteBitSet<u64>,
|
||||
unused_parameters: &'a mut FiniteBitSet<u32>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
|
||||
|
Loading…
Reference in New Issue
Block a user