From 07600c939b594b39f560bc969caca2e92498435a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 9 Jan 2019 18:40:30 +0100 Subject: [PATCH 1/2] Drop "solved" constraints during region expansion Once a region has been expanded to cover a fixed region, a corresponding RegSubVar constraint won't have any effect on the expansion anymore, the same is true for constraints where the variable on the RHS has already reached static scope. By removing those constraints from the set that we're iterating over, we remove a lot of needless overhead in case of slow convergences (i.e. lots of iterations). For the unicode_normalization crate, this about cuts the time required for item_bodies checking in half. --- .../infer/lexical_region_resolve/mod.rs | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index dbf8f270ab0c9..2a93217b9b423 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -13,6 +13,7 @@ use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use smallvec::SmallVec; use std::fmt; use std::u32; use ty::fold::TypeFoldable; @@ -190,19 +191,24 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { match *constraint { Constraint::RegSubVar(a_region, b_vid) => { let b_data = var_values.value_mut(b_vid); - self.expand_node(a_region, b_vid, b_data) + (self.expand_node(a_region, b_vid, b_data), false) } Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) { - VarValue::ErrorValue => false, + VarValue::ErrorValue => (false, false), VarValue::Value(a_region) => { let b_node = var_values.value_mut(b_vid); - self.expand_node(a_region, b_vid, b_node) + let changed = self.expand_node(a_region, b_vid, b_node); + let retain = match *b_node { + VarValue::Value(ReStatic) | VarValue::ErrorValue => false, + _ => true + }; + (changed, retain) } }, Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => { // These constraints are checked after expansion // is done, in `collect_errors`. - false + (false, false) } } }) @@ -710,21 +716,23 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { fn iterate_until_fixed_point(&self, tag: &str, mut body: F) where - F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool, + F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool), { + let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect(); let mut iteration = 0; let mut changed = true; while changed { changed = false; iteration += 1; debug!("---- {} Iteration {}{}", "#", tag, iteration); - for (constraint, origin) in &self.data.constraints { - let edge_changed = body(constraint, origin); + constraints.retain(|(constraint, origin)| { + let (edge_changed, retain) = body(constraint, origin); if edge_changed { debug!("Updated due to constraint {:?}", constraint); changed = true; } - } + retain + }); } debug!("---- {} Complete after {} iteration(s)", tag, iteration); } From 5f402b827726607b04887c7c7b8d8b95cce8f487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 10 Jan 2019 19:28:42 +0100 Subject: [PATCH 2/2] Add a fast path for identical regions in lub_concrete_regions In functions with lots of region constraint, if the fixed point iteration converges only slowly, a lot of the var/var constraints will have equal regions most of the time. Yet, we still perform the LUB calculation and try to intern the result. Especially the latter incurs quite some overhead. This reduces the take taken by the item bodies checking pass for the unicode_normalization crate by about 75%. --- src/librustc/infer/lexical_region_resolve/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 2a93217b9b423..39ce8cc621b49 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -274,6 +274,13 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let tcx = self.tcx(); + + // Equal scopes can show up quite often, if the fixed point + // iteration converges slowly, skip them + if a == b { + return a; + } + match (a, b) { (&ty::ReClosureBound(..), _) | (_, &ty::ReClosureBound(..))