Skip to content

Commit 779f85b

Browse files
committed
Auto merge of #68001 - Marwes:lexical_region_resolve, r=nikomatsakis
perf: Only search potentially changed constraints in lexical_region_resolve Gives a big performance increase to the unicode_normalization benchmark in my testing.
2 parents 35b5157 + 917eb18 commit 779f85b

File tree

1 file changed

+36
-40
lines changed
  • src/librustc/infer/lexical_region_resolve

1 file changed

+36
-40
lines changed

src/librustc/infer/lexical_region_resolve/mod.rs

+36-40
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_data_structures::graph::implementation::{
1919
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
2020
};
2121
use rustc_hir::def_id::DefId;
22-
use rustc_index::bit_set::BitSet;
2322
use rustc_index::vec::{Idx, IndexVec};
2423
use rustc_span::Span;
2524
use std::fmt;
@@ -295,62 +294,59 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
295294
}
296295

297296
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
298-
let mut process_constraint = |constraint: &Constraint<'tcx>| {
299-
let (a_region, b_vid, b_data, retain) = match *constraint {
297+
let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
298+
let mut changes = Vec::new();
299+
for constraint in self.data.constraints.keys() {
300+
let (a_vid, a_region, b_vid, b_data) = match *constraint {
300301
Constraint::RegSubVar(a_region, b_vid) => {
301302
let b_data = var_values.value_mut(b_vid);
302-
(a_region, b_vid, b_data, false)
303+
(None, a_region, b_vid, b_data)
303304
}
304305
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
305-
VarValue::ErrorValue => return (false, false),
306+
VarValue::ErrorValue => continue,
306307
VarValue::Value(a_region) => {
307308
let b_data = var_values.value_mut(b_vid);
308-
let retain = match *b_data {
309-
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
310-
_ => true,
311-
};
312-
(a_region, b_vid, b_data, retain)
309+
(Some(a_vid), a_region, b_vid, b_data)
313310
}
314311
},
315312
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
316313
// These constraints are checked after expansion
317314
// is done, in `collect_errors`.
318-
return (false, false);
315+
continue;
319316
}
320317
};
321-
322-
let changed = self.expand_node(a_region, b_vid, b_data);
323-
(changed, retain)
324-
};
325-
326-
// Using bitsets to track the remaining elements is faster than using a
327-
// `Vec` by itself (which requires removing elements, which requires
328-
// element shuffling, which is slow).
329-
let constraints: Vec<_> = self.data.constraints.keys().collect();
330-
let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
331-
let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
332-
let mut changed = true;
333-
while changed {
334-
changed = false;
335-
for index in live_indices.iter() {
336-
let constraint = constraints[index];
337-
let (edge_changed, retain) = process_constraint(constraint);
338-
changed |= edge_changed;
339-
if !retain {
340-
let changed = killed_indices.insert(index);
341-
debug_assert!(changed);
318+
if self.expand_node(a_region, b_vid, b_data) {
319+
changes.push(b_vid);
320+
}
321+
if let Some(a_vid) = a_vid {
322+
match *b_data {
323+
VarValue::Value(ReStatic) | VarValue::ErrorValue => (),
324+
_ => {
325+
constraints[a_vid].push((a_vid, b_vid));
326+
constraints[b_vid].push((a_vid, b_vid));
327+
}
342328
}
343329
}
344-
live_indices.subtract(&killed_indices);
330+
}
345331

346-
// We could clear `killed_indices` here, but we don't need to and
347-
// it's cheaper not to.
332+
while let Some(vid) = changes.pop() {
333+
constraints[vid].retain(|&(a_vid, b_vid)| {
334+
let a_region = match *var_values.value(a_vid) {
335+
VarValue::ErrorValue => return false,
336+
VarValue::Value(a_region) => a_region,
337+
};
338+
let b_data = var_values.value_mut(b_vid);
339+
if self.expand_node(a_region, b_vid, b_data) {
340+
changes.push(b_vid);
341+
}
342+
match *b_data {
343+
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
344+
_ => true,
345+
}
346+
});
348347
}
349348
}
350349

351-
// This function is very hot in some workloads. There's a single callsite
352-
// so always inlining is ok even though it's large.
353-
#[inline(always)]
354350
fn expand_node(
355351
&self,
356352
a_region: Region<'tcx>,
@@ -790,8 +786,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
790786
self.var_infos[node_idx].origin.span(),
791787
&format!(
792788
"collect_error_for_expanding_node() could not find \
793-
error for var {:?} in universe {:?}, lower_bounds={:#?}, \
794-
upper_bounds={:#?}",
789+
error for var {:?} in universe {:?}, lower_bounds={:#?}, \
790+
upper_bounds={:#?}",
795791
node_idx, node_universe, lower_bounds, upper_bounds
796792
),
797793
);

0 commit comments

Comments
 (0)