Auto merge of #96020 - martingms:optimize-relate_substs, r=nnethercote

Micro-optimize `ty::relate::relate_substs` by avoiding `match`

Was a top-20 hot function in a callgrind profile of compiling `bitmaps-3.1.0`.

Yields some small speedups on that crate and some others according to local benching:

Benchmark | Profile | Scenario | % Change | Significance Factor?
-- | -- | -- | -- | --
bitmaps-3.1.0 | check | full | -1.88% | 9.42x
bitmaps-3.1.0 | debug | full | -1.80% | 8.99x
bitmaps-3.1.0 | opt | full | -1.70% | 8.49x
bitmaps-3.1.0 | check | incr-full | -1.54% | 7.68x
deep-vector | debug | full | 1.52% | 7.61x
bitmaps-3.1.0 | debug | incr-full | -1.45% | 7.26x
bitmaps-3.1.0 | opt | incr-full | -1.39% | 6.95x
nalgebra-0.30.1 | check | full | -0.68% | 3.42x
nalgebra-0.30.1 | debug | full | -0.64% | 3.22x
nalgebra-0.30.1 | opt | full | -0.64% | 3.20x
projection-caching | check | full | -0.61% | 3.05x
nalgebra-0.30.1 | check | incr-full | -0.56% | 2.78x
nalgebra-0.30.1 | opt | incr-full | -0.54% | 2.72x
nalgebra-0.30.1 | debug | incr-full | -0.54% | 2.69x
projection-caching | check | incr-full | -0.50% | 2.51x
tt-muncher | opt | full | -0.48% | 2.42x
projection-caching | opt | full | -0.47% | 2.37x
projection-caching | debug | full | -0.47% | 2.35x
projection-caching | opt | incr-full | -0.44% | 2.21x
projection-caching | debug | incr-full | -0.42% | 2.08x
deeply-nested-multi | check | incr-full | 0.37% | 1.87x
wf-projection-stress-65510 | opt | full | -0.37% | 1.84x
deep-vector | debug | incr-patched: add vec item | -0.32% | 1.61x
projection-caching | debug | incr-unchanged | -0.32% | 1.60x
wf-projection-stress-65510 | check | full | -0.31% | 1.55x
projection-caching | opt | incr-unchanged | -0.31% | 1.53x
wf-projection-stress-65510 | debug | incr-full | -0.30% | 1.51x
wf-projection-stress-65510 | opt | incr-full | -0.30% | 1.51x

r? `@nnethercote`
This commit is contained in:
bors 2022-04-19 10:53:53 +00:00
commit c102c5cfc6
3 changed files with 36 additions and 25 deletions

View file

@ -567,11 +567,17 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
// Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles
// (e.g., #41849).
relate::relate_substs(self, None, a_subst, b_subst)
relate::relate_substs(self, a_subst, b_subst)
} else {
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst)
relate::relate_substs_with_variances(
self,
item_def_id,
&opt_variances,
a_subst,
b_subst,
)
}
}

View file

@ -53,7 +53,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
// performing trait matching (which then performs equality
// unification).
relate::relate_substs(self, None, a_subst, b_subst)
relate::relate_substs(self, a_subst, b_subst)
}
fn relate_with_variance<T: Relate<'tcx>>(

View file

@ -61,7 +61,7 @@ pub trait TypeRelation<'tcx>: Sized {
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst)
relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst)
}
/// Switch variance for the purpose of relating `a` and `b`.
@ -135,29 +135,34 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
}
}
#[inline]
pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
variances: Option<(DefId, &[ty::Variance])>,
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| {
relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
}))
}
pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
ty_def_id: DefId,
variances: &[ty::Variance],
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
let tcx = relation.tcx();
let mut cached_ty = None;
let mut cached_ty = None;
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
let (variance, variance_info) = match variances {
Some((ty_def_id, variances)) => {
let variance = variances[i];
let variance_info = if variance == ty::Invariant {
let ty = *cached_ty
.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()
};
(variance, variance_info)
}
None => (ty::Invariant, ty::VarianceDiagInfo::default()),
let variance = variances[i];
let variance_info = if variance == ty::Invariant {
let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()
};
relation.relate_with_variance(variance, variance_info, a, b)
});
@ -318,7 +323,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs })
}
}
@ -334,7 +339,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
}
}
@ -554,7 +559,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
let substs = relate_substs(relation, None, a_substs, b_substs)?;
let substs = relate_substs(relation, a_substs, b_substs)?;
Ok(tcx.mk_opaque(a_def_id, substs))
}
@ -742,7 +747,7 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
a: ty::ClosureSubsts<'tcx>,
b: ty::ClosureSubsts<'tcx>,
) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::ClosureSubsts { substs })
}
}
@ -753,7 +758,7 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
a: ty::GeneratorSubsts<'tcx>,
b: ty::GeneratorSubsts<'tcx>,
) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::GeneratorSubsts { substs })
}
}
@ -764,7 +769,7 @@ impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
a: SubstsRef<'tcx>,
b: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
relate_substs(relation, None, a, b)
relate_substs(relation, a, b)
}
}