Call skolemize_late_bound_regions only after fast rejection

skolemize_late_bound_regions essentially copies the entire type (most of the times it shouldn't, but it does), and match_impl runs millions of times.

Times compiling rustc, tested with
$ make -j4 rustc-stage1
$ ( time RUSTFLAGS=-Z time-passes make -j4 rustc-stage2 ) # need LLVM time for calibration

Before:
real	21m44.960s
user	29m38.812s
sys	0m14.944s

After:
real	19m31.445s
user	26m47.260s
sys	0m14.952s

Making this is a 10% performance improvement.

LLVM passes took 867 seconds before, 862 seconds after.
This commit is contained in:
Ariel Ben-Yehuda 2015-04-19 23:38:37 +03:00
parent be41e98067
commit 94a1b266f9

View file

@ -532,11 +532,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.repr(self.tcx())); obligation.repr(self.tcx()));
self.infcx.probe(|snapshot| { self.infcx.probe(|snapshot| {
let (skol_obligation_trait_ref, skol_map) = match self.match_impl(impl_def_id, obligation, snapshot) {
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); Ok((substs, skol_map)) => {
match self.match_impl(impl_def_id, obligation, snapshot,
&skol_map, skol_obligation_trait_ref.trait_ref.clone()) {
Ok(substs) => {
let vtable_impl = self.vtable_impl(impl_def_id, let vtable_impl = self.vtable_impl(impl_def_id,
substs, substs,
obligation.cause.clone(), obligation.cause.clone(),
@ -1160,10 +1157,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let all_impls = self.all_impls(def_id); let all_impls = self.all_impls(def_id);
for &impl_def_id in &all_impls { for &impl_def_id in &all_impls {
self.infcx.probe(|snapshot| { self.infcx.probe(|snapshot| {
let (skol_obligation_trait_pred, skol_map) = match self.match_impl(impl_def_id, obligation, snapshot) {
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
match self.match_impl(impl_def_id, obligation, snapshot,
&skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
Ok(_) => { Ok(_) => {
candidates.vec.push(ImplCandidate(impl_def_id)); candidates.vec.push(ImplCandidate(impl_def_id));
} }
@ -2115,11 +2109,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// First, create the substitutions by matching the impl again, // First, create the substitutions by matching the impl again,
// this time not in a probe. // this time not in a probe.
self.infcx.commit_if_ok(|snapshot| { self.infcx.commit_if_ok(|snapshot| {
let (skol_obligation_trait_ref, skol_map) = let (substs, skol_map) =
self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
let substs =
self.rematch_impl(impl_def_id, obligation, self.rematch_impl(impl_def_id, obligation,
snapshot, &skol_map, skol_obligation_trait_ref.trait_ref); snapshot);
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx())); debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(), Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
obligation.recursion_depth + 1, skol_map, snapshot)) obligation.recursion_depth + 1, skol_map, snapshot))
@ -2306,14 +2298,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn rematch_impl(&mut self, fn rematch_impl(&mut self,
impl_def_id: ast::DefId, impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot, snapshot: &infer::CombinedSnapshot)
skol_map: &infer::SkolemizationMap, -> (Normalized<'tcx, Substs<'tcx>>, infer::SkolemizationMap)
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
-> Normalized<'tcx, Substs<'tcx>>
{ {
match self.match_impl(impl_def_id, obligation, snapshot, match self.match_impl(impl_def_id, obligation, snapshot) {
skol_map, skol_obligation_trait_ref) { Ok((substs, skol_map)) => (substs, skol_map),
Ok(substs) => substs,
Err(()) => { Err(()) => {
self.tcx().sess.bug( self.tcx().sess.bug(
&format!("Impl {} was matchable against {} but now is not", &format!("Impl {} was matchable against {} but now is not",
@ -2326,10 +2315,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_impl(&mut self, fn match_impl(&mut self,
impl_def_id: ast::DefId, impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot, snapshot: &infer::CombinedSnapshot)
skol_map: &infer::SkolemizationMap, -> Result<(Normalized<'tcx, Substs<'tcx>>,
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>) infer::SkolemizationMap), ()>
-> Result<Normalized<'tcx, Substs<'tcx>>, ()>
{ {
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap(); let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
@ -2340,6 +2328,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(()); return Err(());
} }
let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
&obligation.predicate,
snapshot);
let skol_obligation_trait_ref = skol_obligation.trait_ref;
let impl_substs = util::fresh_type_vars_for_impl(self.infcx, let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
obligation.cause.span, obligation.cause.span,
impl_def_id); impl_def_id);
@ -2370,17 +2363,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(()); return Err(());
} }
if let Err(e) = self.infcx.leak_check(skol_map, snapshot) { if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
debug!("match_impl: failed leak check due to `{}`", debug!("match_impl: failed leak check due to `{}`",
ty::type_err_to_str(self.tcx(), &e)); ty::type_err_to_str(self.tcx(), &e));
return Err(()); return Err(());
} }
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx())); debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
Ok(Normalized { Ok((Normalized {
value: impl_substs, value: impl_substs,
obligations: impl_trait_ref.obligations obligations: impl_trait_ref.obligations
}) }, skol_map))
} }
fn fast_reject_trait_refs(&mut self, fn fast_reject_trait_refs(&mut self,