Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4a76e6d

Browse files
authoredOct 18, 2019
Rollup merge of rust-lang#65480 - nnethercote:rm-iterate_until_fixed_size, r=nikomatsakis
Speed up `LexicalResolve::expansion()` A couple of improvements that speed up `unicode_normalization` by about 4%. The first commit was enabled by the improvements to `BitSet` iteration in rust-lang#65425. r? @nikomatsakis
2 parents 809b3f0 + d51fee0 commit 4a76e6d

File tree

1 file changed

+29
-27
lines changed
  • src/librustc/infer/lexical_region_resolve

1 file changed

+29
-27
lines changed
 

‎src/librustc/infer/lexical_region_resolve/mod.rs

+29-27
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use rustc_data_structures::fx::FxHashSet;
1919
use rustc_data_structures::graph::implementation::{
2020
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
2121
};
22+
use rustc_index::bit_set::BitSet;
2223
use rustc_index::vec::{Idx, IndexVec};
23-
use smallvec::SmallVec;
2424
use std::fmt;
2525
use syntax_pos::Span;
2626

@@ -304,8 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
304304
}
305305

306306
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
307-
self.iterate_until_fixed_point(|constraint| {
308-
debug!("expansion: constraint={:?}", constraint);
307+
let mut process_constraint = |constraint: &Constraint<'tcx>| {
309308
let (a_region, b_vid, b_data, retain) = match *constraint {
310309
Constraint::RegSubVar(a_region, b_vid) => {
311310
let b_data = var_values.value_mut(b_vid);
@@ -331,7 +330,33 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
331330

332331
let changed = self.expand_node(a_region, b_vid, b_data);
333332
(changed, retain)
334-
})
333+
};
334+
335+
// Using bitsets to track the remaining elements is faster than using a
336+
// `Vec` by itself (which requires removing elements, which requires
337+
// element shuffling, which is slow).
338+
let constraints: Vec<_> = self.data.constraints.keys().collect();
339+
let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
340+
let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
341+
let mut changed = true;
342+
while changed {
343+
changed = false;
344+
for index in live_indices.iter() {
345+
let constraint = constraints[index];
346+
let (edge_changed, retain) = process_constraint(constraint);
347+
if edge_changed {
348+
changed = true;
349+
}
350+
if !retain {
351+
let changed = killed_indices.insert(index);
352+
debug_assert!(changed);
353+
}
354+
}
355+
live_indices.subtract(&killed_indices);
356+
357+
// We could clear `killed_indices` here, but we don't need to and
358+
// it's cheaper not to.
359+
}
335360
}
336361

337362
// This function is very hot in some workloads. There's a single callsite
@@ -866,29 +891,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
866891
}
867892
}
868893

869-
fn iterate_until_fixed_point<F>(&self, mut body: F)
870-
where
871-
F: FnMut(&Constraint<'tcx>) -> (bool, bool),
872-
{
873-
let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
874-
let mut iteration = 0;
875-
let mut changed = true;
876-
while changed {
877-
changed = false;
878-
iteration += 1;
879-
debug!("---- Expansion iteration {}", iteration);
880-
constraints.retain(|constraint| {
881-
let (edge_changed, retain) = body(constraint);
882-
if edge_changed {
883-
debug!("updated due to constraint {:?}", constraint);
884-
changed = true;
885-
}
886-
retain
887-
});
888-
}
889-
debug!("---- Expansion complete after {} iteration(s)", iteration);
890-
}
891-
892894
fn bound_is_met(
893895
&self,
894896
bound: &VerifyBound<'tcx>,

0 commit comments

Comments
 (0)
Please sign in to comment.