diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index f21c898a28a..65fdf10a86d 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -19,6 +19,20 @@ use bitslice::{bitwise, Union, Subtract, Intersect}; use indexed_vec::Idx; use rustc_serialize; +/// This is implemented by all the index sets so that IdxSet::union() can be +/// passed any type of index set. +pub trait UnionIntoIdxSet { + // Performs `other = other | self`. + fn union_into(&self, other: &mut IdxSet) -> bool; +} + +/// This is implemented by all the index sets so that IdxSet::subtract() can be +/// passed any type of index set. +pub trait SubtractFromIdxSet { + // Performs `other = other - self`. + fn subtract_from(&self, other: &mut IdxSet) -> bool; +} + /// Represents a set of some element type E, where each E is identified by some /// unique index type `T`. /// @@ -68,34 +82,34 @@ impl fmt::Debug for IdxSet { } impl IdxSet { - fn new(init: Word, universe_size: usize) -> Self { - let num_words = (universe_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD; + fn new(init: Word, domain_size: usize) -> Self { + let num_words = (domain_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD; IdxSet { _pd: Default::default(), bits: vec![init; num_words], } } - /// Creates set holding every element whose index falls in range 0..universe_size. - pub fn new_filled(universe_size: usize) -> Self { - let mut result = Self::new(!0, universe_size); - result.trim_to(universe_size); + /// Creates set holding every element whose index falls in range 0..domain_size. + pub fn new_filled(domain_size: usize) -> Self { + let mut result = Self::new(!0, domain_size); + result.trim_to(domain_size); result } /// Creates set holding no elements. - pub fn new_empty(universe_size: usize) -> Self { - Self::new(0, universe_size) + pub fn new_empty(domain_size: usize) -> Self { + Self::new(0, domain_size) } /// Duplicates as a hybrid set. pub fn to_hybrid(&self) -> HybridIdxSet { - // This universe_size may be slightly larger than the one specified + // This domain_size may be slightly larger than the one specified // upon creation, due to rounding up to a whole word. That's ok. - let universe_size = self.bits.len() * BITS_PER_WORD; + let domain_size = self.bits.len() * BITS_PER_WORD; // Note: we currently don't bother trying to make a Sparse set. - HybridIdxSet::Dense(self.to_owned(), universe_size) + HybridIdxSet::Dense(self.to_owned(), domain_size) } /// Removes all elements @@ -105,19 +119,19 @@ impl IdxSet { } } - /// Sets all elements up to `universe_size` - pub fn set_up_to(&mut self, universe_size: usize) { + /// Sets all elements up to `domain_size` + pub fn set_up_to(&mut self, domain_size: usize) { for b in &mut self.bits { *b = !0; } - self.trim_to(universe_size); + self.trim_to(domain_size); } - /// Clear all elements above `universe_size`. - fn trim_to(&mut self, universe_size: usize) { + /// Clear all elements above `domain_size`. + fn trim_to(&mut self, domain_size: usize) { // `trim_block` is the first block where some bits have // to be cleared. - let trim_block = universe_size / BITS_PER_WORD; + let trim_block = domain_size / BITS_PER_WORD; // all the blocks above it have to be completely cleared. if trim_block < self.bits.len() { @@ -125,9 +139,9 @@ impl IdxSet { *b = 0; } - // at that block, the `universe_size % BITS_PER_WORD` lsbs + // at that block, the `domain_size % BITS_PER_WORD` LSBs // should remain. - let remaining_bits = universe_size % BITS_PER_WORD; + let remaining_bits = domain_size % BITS_PER_WORD; let mask = (1< IdxSet { /// Set `self = self | other` and return true if `self` changed /// (i.e., if new bits were added). - pub fn union(&mut self, other: &IdxSet) -> bool { - bitwise(self.words_mut(), other.words(), &Union) - } - - /// Like `union()`, but takes a `SparseIdxSet` argument. - fn union_sparse(&mut self, other: &SparseIdxSet) -> bool { - let mut changed = false; - for elem in other.iter() { - changed |= self.add(&elem); - } - changed - } - - /// Like `union()`, but takes a `HybridIdxSet` argument. - pub fn union_hybrid(&mut self, other: &HybridIdxSet) -> bool { - match other { - HybridIdxSet::Sparse(sparse, _) => self.union_sparse(sparse), - HybridIdxSet::Dense(dense, _) => self.union(dense), - } + pub fn union(&mut self, other: &impl UnionIntoIdxSet) -> bool { + other.union_into(self) } /// Set `self = self - other` and return true if `self` changed. /// (i.e., if any bits were removed). - pub fn subtract(&mut self, other: &IdxSet) -> bool { - bitwise(self.words_mut(), other.words(), &Subtract) - } - - /// Like `subtract()`, but takes a `SparseIdxSet` argument. - fn subtract_sparse(&mut self, other: &SparseIdxSet) -> bool { - let mut changed = false; - for elem in other.iter() { - changed |= self.remove(&elem); - } - changed - } - - /// Like `subtract()`, but takes a `HybridIdxSet` argument. - pub fn subtract_hybrid(&mut self, other: &HybridIdxSet) -> bool { - match other { - HybridIdxSet::Sparse(sparse, _) => self.subtract_sparse(sparse), - HybridIdxSet::Dense(dense, _) => self.subtract(dense), - } + pub fn subtract(&mut self, other: &impl SubtractFromIdxSet) -> bool { + other.subtract_from(self) } /// Set `self = self & other` and return true if `self` changed. @@ -223,6 +203,18 @@ impl IdxSet { } } +impl UnionIntoIdxSet for IdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + bitwise(other.words_mut(), self.words(), &Union) + } +} + +impl SubtractFromIdxSet for IdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + bitwise(other.words_mut(), self.words(), &Subtract) + } +} + pub struct Iter<'a, T: Idx> { cur: Option<(Word, usize)>, iter: iter::Enumerate>, @@ -293,8 +285,8 @@ impl SparseIdxSet { } } - fn to_dense(&self, universe_size: usize) -> IdxSet { - let mut dense = IdxSet::new_empty(universe_size); + fn to_dense(&self, domain_size: usize) -> IdxSet { + let mut dense = IdxSet::new_empty(domain_size); for elem in self.0.iter() { dense.add(elem); } @@ -308,6 +300,26 @@ impl SparseIdxSet { } } +impl UnionIntoIdxSet for SparseIdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.add(&elem); + } + changed + } +} + +impl SubtractFromIdxSet for SparseIdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + let mut changed = false; + for elem in self.iter() { + changed |= other.remove(&elem); + } + changed + } +} + pub struct SparseIter<'a, T: Idx> { iter: slice::Iter<'a, T>, } @@ -323,7 +335,7 @@ impl<'a, T: Idx> Iterator for SparseIter<'a, T> { /// Like IdxSet, but with a hybrid representation: sparse when there are few /// elements in the set, but dense when there are many. It's especially /// efficient for sets that typically have a small number of elements, but a -/// large `universe_size`, and are cleared frequently. +/// large `domain_size`, and are cleared frequently. #[derive(Clone, Debug)] pub enum HybridIdxSet { Sparse(SparseIdxSet, usize), @@ -331,20 +343,16 @@ pub enum HybridIdxSet { } impl HybridIdxSet { - pub fn new_empty(universe_size: usize) -> Self { - HybridIdxSet::Sparse(SparseIdxSet::new(), universe_size) - } - - fn universe_size(&mut self) -> usize { - match *self { - HybridIdxSet::Sparse(_, size) => size, - HybridIdxSet::Dense(_, size) => size, - } + pub fn new_empty(domain_size: usize) -> Self { + HybridIdxSet::Sparse(SparseIdxSet::new(), domain_size) } pub fn clear(&mut self) { - let universe_size = self.universe_size(); - *self = HybridIdxSet::new_empty(universe_size); + let domain_size = match *self { + HybridIdxSet::Sparse(_, size) => size, + HybridIdxSet::Dense(_, size) => size, + }; + *self = HybridIdxSet::new_empty(domain_size); } /// Returns true iff set `self` contains `elem`. @@ -374,11 +382,11 @@ impl HybridIdxSet { // appease the borrow checker. let dummy = HybridIdxSet::Sparse(SparseIdxSet::new(), 0); match mem::replace(self, dummy) { - HybridIdxSet::Sparse(sparse, universe_size) => { - let mut dense = sparse.to_dense(universe_size); + HybridIdxSet::Sparse(sparse, domain_size) => { + let mut dense = sparse.to_dense(domain_size); let changed = dense.add(elem); assert!(changed); - mem::replace(self, HybridIdxSet::Dense(dense, universe_size)); + mem::replace(self, HybridIdxSet::Dense(dense, domain_size)); changed } _ => panic!("impossible"), @@ -401,7 +409,7 @@ impl HybridIdxSet { /// Converts to a dense set, consuming itself in the process. pub fn to_dense(self) -> IdxSet { match self { - HybridIdxSet::Sparse(sparse, universe_size) => sparse.to_dense(universe_size), + HybridIdxSet::Sparse(sparse, domain_size) => sparse.to_dense(domain_size), HybridIdxSet::Dense(dense, _) => dense, } } @@ -415,6 +423,24 @@ impl HybridIdxSet { } } +impl UnionIntoIdxSet for HybridIdxSet { + fn union_into(&self, other: &mut IdxSet) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.union_into(other), + HybridIdxSet::Dense(dense, _) => dense.union_into(other), + } + } +} + +impl SubtractFromIdxSet for HybridIdxSet { + fn subtract_from(&self, other: &mut IdxSet) -> bool { + match self { + HybridIdxSet::Sparse(sparse, _) => sparse.subtract_from(other), + HybridIdxSet::Dense(dense, _) => dense.subtract_from(other), + } + } +} + pub enum HybridIter<'a, T: Idx> { Sparse(SparseIter<'a, T>), Dense(Iter<'a, T>), diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 0dfc5b5b4b7..1f7faa21a12 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -129,8 +129,8 @@ where F: FnOnce(Iter), { let mut curr_state = self.curr_state.clone(); - curr_state.union_hybrid(&self.stmt_gen); - curr_state.subtract_hybrid(&self.stmt_kill); + curr_state.union(&self.stmt_gen); + curr_state.subtract(&self.stmt_kill); f(curr_state.iter()); } } @@ -193,8 +193,8 @@ impl FlowsAtLocation for FlowAtLocation } fn apply_local_effect(&mut self, _loc: Location) { - self.curr_state.union_hybrid(&self.stmt_gen); - self.curr_state.subtract_hybrid(&self.stmt_kill); + self.curr_state.union(&self.stmt_gen); + self.curr_state.subtract(&self.stmt_kill); } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 598e827b256..48d34997868 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -241,8 +241,8 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: Bi let sets = self.builder.flow_state.sets.for_block(bb.index()); debug_assert!(in_out.words().len() == sets.on_entry.words().len()); in_out.overwrite(sets.on_entry); - in_out.union_hybrid(sets.gen_set); - in_out.subtract_hybrid(sets.kill_set); + in_out.union(sets.gen_set); + in_out.subtract(sets.kill_set); } self.builder.propagate_bits_into_graph_successors_of( in_out, (bb, bb_data), &mut dirty_queue); @@ -534,8 +534,8 @@ impl<'a, E:Idx> BlockSets<'a, E> { } fn apply_local_effect(&mut self) { - self.on_entry.union_hybrid(&self.gen_set); - self.on_entry.subtract_hybrid(&self.kill_set); + self.on_entry.union(self.gen_set); + self.on_entry.subtract(self.kill_set); } } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 63675f056ab..eda7de0fd79 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -209,8 +209,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &mut sets, Location { block: bb, statement_index: j }); results.0.operator.statement_effect( &mut sets, Location { block: bb, statement_index: j }); - sets.on_entry.union_hybrid(sets.gen_set); - sets.on_entry.subtract_hybrid(sets.kill_set); + sets.on_entry.union(sets.gen_set); + sets.on_entry.subtract(sets.kill_set); } results.0.operator.before_terminator_effect(