Skip to content

Commit fe4e15c

Browse files
committed
Auto merge of #68001 - Marwes:lexical_region_resolve, r=<try>
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 f48e576 + d9f3888 commit fe4e15c

File tree

1 file changed

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

1 file changed

+34
-40
lines changed

src/librustc/infer/lexical_region_resolve/mod.rs

+34-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;
@@ -297,64 +296,59 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
297296
}
298297

299298
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
300-
let mut process_constraint = |constraint: &Constraint<'tcx>| {
301-
let (a_region, b_vid, b_data, retain) = match *constraint {
299+
let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
300+
let mut changes = Vec::new();
301+
for constraint in self.data.constraints.keys() {
302+
let (a_vid, a_region, b_vid, b_data) = match *constraint {
302303
Constraint::RegSubVar(a_region, b_vid) => {
303304
let b_data = var_values.value_mut(b_vid);
304-
(a_region, b_vid, b_data, false)
305+
(None, a_region, b_vid, b_data)
305306
}
306307
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
307-
VarValue::ErrorValue => return (false, false),
308+
VarValue::ErrorValue => continue,
308309
VarValue::Value(a_region) => {
309310
let b_data = var_values.value_mut(b_vid);
310-
let retain = match *b_data {
311-
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
312-
_ => true,
313-
};
314-
(a_region, b_vid, b_data, retain)
311+
(Some(a_vid), a_region, b_vid, b_data)
315312
}
316313
},
317314
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
318315
// These constraints are checked after expansion
319316
// is done, in `collect_errors`.
320-
return (false, false);
317+
continue;
321318
}
322319
};
323-
324-
let changed = self.expand_node(a_region, b_vid, b_data);
325-
(changed, retain)
326-
};
327-
328-
// Using bitsets to track the remaining elements is faster than using a
329-
// `Vec` by itself (which requires removing elements, which requires
330-
// element shuffling, which is slow).
331-
let constraints: Vec<_> = self.data.constraints.keys().collect();
332-
let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
333-
let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
334-
let mut changed = true;
335-
while changed {
336-
changed = false;
337-
for index in live_indices.iter() {
338-
let constraint = constraints[index];
339-
let (edge_changed, retain) = process_constraint(constraint);
340-
if edge_changed {
341-
changed = true;
342-
}
343-
if !retain {
344-
let changed = killed_indices.insert(index);
345-
debug_assert!(changed);
320+
if self.expand_node(a_region, b_vid, b_data) {
321+
changes.push(b_vid);
322+
}
323+
if let Some(a_vid) = a_vid {
324+
match *b_data {
325+
VarValue::Value(ReStatic) | VarValue::ErrorValue => (),
326+
_ => {
327+
constraints[a_vid].push((a_vid, b_vid));
328+
constraints[b_vid].push((a_vid, b_vid));
329+
}
346330
}
347331
}
348-
live_indices.subtract(&killed_indices);
332+
}
349333

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

355-
// This function is very hot in some workloads. There's a single callsite
356-
// so always inlining is ok even though it's large.
357-
#[inline(always)]
358352
fn expand_node(
359353
&self,
360354
a_region: Region<'tcx>,

0 commit comments

Comments
 (0)