From 70b136d532460d2e35456d303726be736a3adb3d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Oct 2019 15:16:51 +1100 Subject: [PATCH] Use a `BitSet` in `LexicalResolver::iterate_until_fixed_point()`. This wins 3% on `unicode_normalization`. --- .../infer/lexical_region_resolve/mod.rs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 6f55ade1e8612..a8d1b26476065 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -19,8 +19,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; +use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use smallvec::SmallVec; use std::fmt; use syntax_pos::Span; @@ -870,21 +870,34 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { where F: FnMut(&Constraint<'tcx>) -> (bool, bool), { - let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect(); + // Using bitsets to track the remaining elements is faster than using a + // `Vec` by itself (which requires removing elements, which requires + // element shuffling, which is slow). + let constraints: Vec<_> = self.data.constraints.keys().collect(); + let mut live_indices: BitSet = BitSet::new_filled(constraints.len()); + let mut killed_indices: BitSet = BitSet::new_empty(constraints.len()); let mut iteration = 0; let mut changed = true; while changed { changed = false; iteration += 1; debug!("---- Expansion iteration {}", iteration); - constraints.retain(|constraint| { + for index in live_indices.iter() { + let constraint = constraints[index]; let (edge_changed, retain) = body(constraint); if edge_changed { debug!("updated due to constraint {:?}", constraint); changed = true; } - retain - }); + if !retain { + let changed = killed_indices.insert(index); + debug_assert!(changed); + } + } + live_indices.subtract(&killed_indices); + + // We could clear `killed_indices` here, but we don't need to and + // it's cheaper not to. } debug!("---- Expansion complete after {} iteration(s)", iteration); }